mirror of
https://github.com/folke/lazy.nvim.git
synced 2025-06-28 11:24:14 +00:00
Compare commits
No commits in common. "main" and "v10.21.1" have entirely different histories.
85 changed files with 2699 additions and 124148 deletions
11
.busted
11
.busted
|
@ -1,11 +0,0 @@
|
||||||
return {
|
|
||||||
_all = {
|
|
||||||
coverage = false,
|
|
||||||
},
|
|
||||||
default = {
|
|
||||||
verbose = true,
|
|
||||||
},
|
|
||||||
tests = {
|
|
||||||
verbose = true,
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
insert_final_newline = true
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
charset = utf-8
|
|
3
.github/.release-please-manifest.json
vendored
3
.github/.release-please-manifest.json
vendored
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
".": "11.17.1"
|
|
||||||
}
|
|
37
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
37
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
@ -6,10 +6,7 @@ body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
**Before** reporting an issue, make sure to read the [documentation](https://github.com/folke/lazy.nvim)
|
**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.
|
||||||
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
|
- type: checkboxes
|
||||||
attributes:
|
attributes:
|
||||||
label: Did you check docs and existing issues?
|
label: Did you check docs and existing issues?
|
||||||
|
@ -17,8 +14,6 @@ body:
|
||||||
options:
|
options:
|
||||||
- label: I have read all the lazy.nvim docs
|
- label: I have read all the lazy.nvim docs
|
||||||
required: true
|
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
|
- label: I have searched the existing issues of lazy.nvim
|
||||||
required: true
|
required: true
|
||||||
- label: I have searched the existing issues of plugins related to this issue
|
- label: I have searched the existing issues of plugins related to this issue
|
||||||
|
@ -62,14 +57,32 @@ body:
|
||||||
label: Repro
|
label: Repro
|
||||||
description: Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua`
|
description: Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua`
|
||||||
value: |
|
value: |
|
||||||
vim.env.LAZY_STDPATH = ".repro"
|
-- DO NOT change the paths and don't remove the colorscheme
|
||||||
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()
|
local root = vim.fn.fnamemodify("./.repro", ":p")
|
||||||
|
|
||||||
require("lazy.minit").repro({
|
-- set stdpaths to use .repro
|
||||||
spec = {
|
for _, name in ipairs({ "config", "data", "state", "cache" }) do
|
||||||
|
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
|
||||||
|
end
|
||||||
|
|
||||||
|
-- bootstrap lazy
|
||||||
|
local lazypath = root .. "/plugins/lazy.nvim"
|
||||||
|
if not vim.loop.fs_stat(lazypath) then
|
||||||
|
vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath, })
|
||||||
|
end
|
||||||
|
vim.opt.runtimepath:prepend(lazypath)
|
||||||
|
|
||||||
|
-- install plugins
|
||||||
|
local plugins = {
|
||||||
|
"folke/tokyonight.nvim",
|
||||||
-- add any other plugins here
|
-- add any other plugins here
|
||||||
},
|
}
|
||||||
|
require("lazy").setup(plugins, {
|
||||||
|
root = root .. "/plugins",
|
||||||
})
|
})
|
||||||
render: lua
|
|
||||||
|
vim.cmd.colorscheme("tokyonight")
|
||||||
|
-- add anything else here
|
||||||
|
render: Lua
|
||||||
validations:
|
validations:
|
||||||
required: false
|
required: false
|
||||||
|
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
5
.github/ISSUE_TEMPLATE/config.yml
vendored
|
@ -1,5 +0,0 @@
|
||||||
blank_issues_enabled: false
|
|
||||||
contact_links:
|
|
||||||
- name: Ask a question
|
|
||||||
url: https://github.com/folke/lazy.nvim/discussions
|
|
||||||
about: Use Github discussions instead
|
|
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -1,16 +0,0 @@
|
||||||
## 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
6
.github/dependabot.yml
vendored
|
@ -1,6 +0,0 @@
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
9
.github/release-please-config.json
vendored
9
.github/release-please-config.json
vendored
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
|
|
||||||
"packages": {
|
|
||||||
".": {
|
|
||||||
"release-type": "simple",
|
|
||||||
"extra-files": ["lua/lazy/core/config.lua"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
75
.github/workflows/ci.yml
vendored
75
.github/workflows/ci.yml
vendored
|
@ -1,15 +1,74 @@
|
||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main, master]
|
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
tests:
|
||||||
uses: folke/github/.github/workflows/ci.yml@main
|
strategy:
|
||||||
secrets: inherit
|
matrix:
|
||||||
|
# os: [ubuntu-latest, windows-latest]
|
||||||
|
os: [ubuntu-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Install Neovim
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/nvim
|
||||||
|
wget -q https://github.com/neovim/neovim/releases/download/nightly/nvim.appimage -O /tmp/nvim/nvim.appimage
|
||||||
|
cd /tmp/nvim
|
||||||
|
chmod a+x ./nvim.appimage
|
||||||
|
./nvim.appimage --appimage-extract
|
||||||
|
echo "/tmp/nvim/squashfs-root/usr/bin/" >> $GITHUB_PATH
|
||||||
|
- name: Run Tests
|
||||||
|
run: |
|
||||||
|
nvim --version
|
||||||
|
[ ! -d tests ] && exit 0
|
||||||
|
nvim --headless -u tests/init.lua -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/init.lua', sequential = true}"
|
||||||
|
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:
|
with:
|
||||||
plugin: lazy.nvim
|
vimdoc: lazy.nvim
|
||||||
repo: folke/lazy.nvim
|
version: "Neovim >= 0.8.0"
|
||||||
docs: false
|
demojify: true
|
||||||
|
treesitter: 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
|
||||||
|
id: release
|
||||||
|
with:
|
||||||
|
release-type: simple
|
||||||
|
package-name: lazy.nvim
|
||||||
|
extra-files: |
|
||||||
|
lua/lazy/core/config.lua
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: tag stable versions
|
||||||
|
if: ${{ steps.release.outputs.release_created }}
|
||||||
|
run: |
|
||||||
|
git config user.name github-actions[bot]
|
||||||
|
git config user.email github-actions[bot]@users.noreply.github.com
|
||||||
|
git remote add gh-token "https://${{ secrets.GITHUB_TOKEN }}@github.com/google-github-actions/release-please-action.git"
|
||||||
|
git tag -d stable || true
|
||||||
|
git push origin :stable || true
|
||||||
|
git tag -a stable -m "Last Stable Release"
|
||||||
|
git push origin stable
|
||||||
|
|
30
.github/workflows/community.yml
vendored
30
.github/workflows/community.yml
vendored
|
@ -1,30 +0,0 @@
|
||||||
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
19
.github/workflows/docs.yml
vendored
|
@ -1,19 +0,0 @@
|
||||||
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
8
.github/workflows/labeler.yml
vendored
|
@ -1,8 +0,0 @@
|
||||||
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
18
.github/workflows/pr.yml
vendored
|
@ -1,18 +0,0 @@
|
||||||
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
11
.github/workflows/stale.yml
vendored
|
@ -1,11 +0,0 @@
|
||||||
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
13
.github/workflows/update.yml
vendored
|
@ -1,13 +0,0 @@
|
||||||
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
|
|
15
.gitignore
vendored
15
.gitignore
vendored
|
@ -1,9 +1,8 @@
|
||||||
*.log
|
|
||||||
/.repro
|
|
||||||
/.tests
|
|
||||||
/build
|
|
||||||
/debug
|
|
||||||
/doc/tags
|
|
||||||
foo.*
|
|
||||||
node_modules
|
|
||||||
tt.*
|
tt.*
|
||||||
|
.tests
|
||||||
|
doc/tags
|
||||||
|
debug
|
||||||
|
.repro
|
||||||
|
foo.*
|
||||||
|
*.log
|
||||||
|
data
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
lua/lazy/community/_generated.lua
|
|
524
CHANGELOG.md
524
CHANGELOG.md
|
@ -1,529 +1,5 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/1c9ba3704564a2e34a22191bb89678680ffeb245))
|
|
||||||
* **meta:** rebuild dirty right after disable. See [#1889](https://github.com/folke/lazy.nvim/issues/1889) ([d51cf69](https://github.com/folke/lazy.nvim/commit/d51cf6978321d659e68a8bc38ee806bd2517a196))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/a9c660d6ef1b396869d3d951760aa7a3dbfe575f))
|
|
||||||
* **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](https://github.com/folke/lazy.nvim/commit/c6a57a3534d3494bcc5ff9b0586e141bdb0280eb))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **config:** add missing space on the default debug icon ([#1879](https://github.com/folke/lazy.nvim/issues/1879)) ([4df5c4d](https://github.com/folke/lazy.nvim/commit/4df5c4d65a3bbf801edd9ec55fb1ae55cfa72dd0))
|
|
||||||
* **meta:** disable top-level specs before the rest. Closes [#1889](https://github.com/folke/lazy.nvim/issues/1889) ([f81a3fb](https://github.com/folke/lazy.nvim/commit/f81a3fb7feaf460ec7c8c983682b4a693b18fdd4))
|
|
||||||
* **ui:** do not show virt_lines for messages ([#1904](https://github.com/folke/lazy.nvim/issues/1904)) ([f15a939](https://github.com/folke/lazy.nvim/commit/f15a93907ddad3d9139aea465ae18336d87f5ce6))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/805b85c2ea3bd6f9506ef22cbd6e3a39172b5b08))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/703be1dda35e142e76e94e7503cf67d6b98a1d35)), closes [#1842](https://github.com/folke/lazy.nvim/issues/1842)
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/ee64abc76be2b237b95d241a924b0323005b868a))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **plugin:** don't check if dir exists for virtual plugins ([656cf43](https://github.com/folke/lazy.nvim/commit/656cf4309396b7b8b62984e923bf8d8a0013f7d7))
|
|
||||||
* **render:** show correct key for home. Fixes [#1796](https://github.com/folke/lazy.nvim/issues/1796) ([b08dba8](https://github.com/folke/lazy.nvim/commit/b08dba8107b5bdaaa007f18cf6c0cc0e0fd576aa))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/9570a5ae7b17dcde4718c7458fd986c10f015a99))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/aca30f63619a7492ecdea8833a065cf83c80f764))
|
|
||||||
* **completion:** check if command string is a prefix of Lazy ([#1760](https://github.com/folke/lazy.nvim/issues/1760)) ([e9fd76e](https://github.com/folke/lazy.nvim/commit/e9fd76e239cc18da289f9a3f80f35fa16b003175)), closes [#1758](https://github.com/folke/lazy.nvim/issues/1758)
|
|
||||||
* **docs:** always update helptags for local plugins ([60cf258](https://github.com/folke/lazy.nvim/commit/60cf258a9ae7fffe04bb31141141a91845158dcc))
|
|
||||||
* **luarocks:** try to install from root manifest ([#1687](https://github.com/folke/lazy.nvim/issues/1687)) ([591ef40](https://github.com/folke/lazy.nvim/commit/591ef40f2da3a26fbcc0466988cd6fe45ca68cae))
|
|
||||||
* **rocks:** add lib64 plugin directory to package.cpath ([#1717](https://github.com/folke/lazy.nvim/issues/1717)) ([80da254](https://github.com/folke/lazy.nvim/commit/80da254e645f579c28394ee0f08f75a9c9481744))
|
|
||||||
* **rockspec:** allow binary lua files. Fixes [#1800](https://github.com/folke/lazy.nvim/issues/1800) ([408449a](https://github.com/folke/lazy.nvim/commit/408449a59adb8c2a31c32fff606676b32ce4552a))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/7108809ab18dc1b1e6f402b29e2e1d35a5d311d5))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/d5686efbd00942b3e38de7c08b8df69d961b02f0))
|
|
||||||
* **plugin:** improve error handling and show better error message ([c02268a](https://github.com/folke/lazy.nvim/commit/c02268ac6e6aab92249d020d75efc588bd9d24fa))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **plugin:** make .lazy.lua work again ([b4a5a12](https://github.com/folke/lazy.nvim/commit/b4a5a1209e4c64fa67aedf721a383541a64056d1))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/7d29719ade6f5a269e3b7d08b246641b5b079aaa))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/34b0126e5b3966f1dbe148d6f8450213115e76b2))
|
|
||||||
* **loader:** explicitely set package.loaded.modname to nil to prevent recursive loading errors ([12f2c74](https://github.com/folke/lazy.nvim/commit/12f2c74244cc768d97c83972aa63722389b5d96d))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/a692bf86883457f45fe3f773bfc8bc4d9e4b070c))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/18d1c1b47e175cd58dc12bf4792ef4e9a50505fa))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/5bdb12a038e5a72cc793f38893f1a9c9fb741759))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/6ca90a21202808796418e46d3cebfbb5a44e54a2))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/d731a6b005fd239e85e555bd57362382f6c1e461))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/93499c5deb37641c6cf71528a93f101d186b409f))
|
|
||||||
* **lockfile:** ensure newline at EOF for lockfile ([#1639](https://github.com/folke/lazy.nvim/issues/1639)) ([7ed9f71](https://github.com/folke/lazy.nvim/commit/7ed9f7173cdec71a057053d7e6efc20c2c230b95))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/17473db1d79ea30e06126834be7fd95ca511557b))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **minit:** add tests to package.path when running busted (helpers.lua etc) ([fadebdc](https://github.com/folke/lazy.nvim/commit/fadebdc76b71a1d3658a88a025c6c8fb4749e0f8))
|
|
||||||
* **util:** strip `-lua` in normname ([54b003c](https://github.com/folke/lazy.nvim/commit/54b003c650f07b771e61566f7be2629beb2b781f))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/f0324defdd43be8aa14aaf3a794ff3d5581f36ba))
|
|
||||||
* **ui:** don't treat suspended as headless. Closes [#1626](https://github.com/folke/lazy.nvim/issues/1626) ([2dfccd7](https://github.com/folke/lazy.nvim/commit/2dfccd7b948beb26d8bcff7f9113a3a5c85cbc4a))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/72c0dc9462ab3bf1a68198afabc1eb4e2940d299))
|
|
||||||
|
|
||||||
## [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](https://github.com/folke/lazy.nvim/commit/81d2bfffdc8c84a40d25cae7fd4800178c19a138))
|
|
||||||
|
|
||||||
## [11.10.1](https://github.com/folke/lazy.nvim/compare/v11.10.0...v11.10.1) (2024-07-05)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **lockfile:** keep cond=false and enabed=false in lockfile. Fixes [#1535](https://github.com/folke/lazy.nvim/issues/1535). Fixes [#1606](https://github.com/folke/lazy.nvim/issues/1606) ([baac551](https://github.com/folke/lazy.nvim/commit/baac5517770abd6eee63d11cf4791ef5bf5702e8))
|
|
||||||
|
|
||||||
## [11.10.0](https://github.com/folke/lazy.nvim/compare/v11.9.2...v11.10.0) (2024-07-04)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **profiling:** merge VeryLazy stats and show startuptime in profile view ([0f2786b](https://github.com/folke/lazy.nvim/commit/0f2786bcc91347188627534471ee75c3f6f16b2d))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **config:** determine headless only during startup. Fixes [#1608](https://github.com/folke/lazy.nvim/issues/1608) ([6fdd904](https://github.com/folke/lazy.nvim/commit/6fdd904ee45b66d933c5d2f72bcec337e13744f8))
|
|
||||||
* **plugin:** local spec name ([923e1aa](https://github.com/folke/lazy.nvim/commit/923e1aa7a49d945afa4c03da4f8ff052cd6d14a6))
|
|
||||||
|
|
||||||
## [11.9.2](https://github.com/folke/lazy.nvim/compare/v11.9.1...v11.9.2) (2024-07-02)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **async:** make asyncs abortable ([1fad617](https://github.com/folke/lazy.nvim/commit/1fad61712bd3937dda925775a7736b8efbcbf1a7))
|
|
||||||
* **health:** check for errors when executing commands. Closes [#1599](https://github.com/folke/lazy.nvim/issues/1599) ([d0921f5](https://github.com/folke/lazy.nvim/commit/d0921f5b9b3d2c5e09618da55a018228edcc4d16))
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **plugin:** minor optim to resolve imports a bit faster ([a9d7ade](https://github.com/folke/lazy.nvim/commit/a9d7ade203b3f3ee3058c082c62afdf8e4bcb416))
|
|
||||||
|
|
||||||
## [11.9.1](https://github.com/folke/lazy.nvim/compare/v11.9.0...v11.9.1) (2024-06-30)
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* automatically suspend the scheduler when all threads are waiting ([#1591](https://github.com/folke/lazy.nvim/issues/1591)) ([c7ed87f](https://github.com/folke/lazy.nvim/commit/c7ed87f9ca03ea412134d6a6ea55b43232eb6b0c))
|
|
||||||
* suspend when tasks are active ([2f4ac03](https://github.com/folke/lazy.nvim/commit/2f4ac035bcc66292250de7134d73007b147f64e8))
|
|
||||||
|
|
||||||
## [11.9.0](https://github.com/folke/lazy.nvim/compare/v11.8.2...v11.9.0) (2024-06-29)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **ui:** use [[ & ]] to navigate between plugins. Fixes [#1463](https://github.com/folke/lazy.nvim/issues/1463) ([5e3c112](https://github.com/folke/lazy.nvim/commit/5e3c112cb32c9cb6e8622aab4446358e039def7c))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **ui:** when closing details, jump to plugin header. Closes [#1338](https://github.com/folke/lazy.nvim/issues/1338) ([3772914](https://github.com/folke/lazy.nvim/commit/37729140751577e87318c137d90d0e6bb00ceff1))
|
|
||||||
|
|
||||||
## [11.8.2](https://github.com/folke/lazy.nvim/compare/v11.8.1...v11.8.2) (2024-06-29)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **process:** deal with process errors ([a75d950](https://github.com/folke/lazy.nvim/commit/a75d950b8f356733ad2d20c4bdb794179e6d4ff1))
|
|
||||||
* **ui:** save/restore view right before/after rendering ([5d334b9](https://github.com/folke/lazy.nvim/commit/5d334b9f579aacd09603dd9e19b6730fbfcf4c72))
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **rocks:** `vim.fn.executable` is slow on WSL2, so only check for `luarocks` when needed. Closes [#1585](https://github.com/folke/lazy.nvim/issues/1585) ([9ab3061](https://github.com/folke/lazy.nvim/commit/9ab306169060eeab7ebca00653318683e72ab62d))
|
|
||||||
|
|
||||||
## [11.8.1](https://github.com/folke/lazy.nvim/compare/v11.8.0...v11.8.1) (2024-06-29)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **async:** remove debug assert ([3513227](https://github.com/folke/lazy.nvim/commit/3513227a9a41c8e6366e1719f4cefbe891ca73d2))
|
|
||||||
|
|
||||||
## [11.8.0](https://github.com/folke/lazy.nvim/compare/v11.7.0...v11.8.0) (2024-06-29)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **plugin:** allow loading specs without pkg ([695a058](https://github.com/folke/lazy.nvim/commit/695a05872a5b44e366e5532eb2fe38a64fae8357))
|
|
||||||
|
|
||||||
## [11.7.0](https://github.com/folke/lazy.nvim/compare/v11.6.0...v11.7.0) (2024-06-29)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **minit:** fallback to habamax when no colorscheme set ([88f4d13](https://github.com/folke/lazy.nvim/commit/88f4d13e5f489eb30959db03a94ebfa10a78b47f))
|
|
||||||
|
|
||||||
## [11.6.0](https://github.com/folke/lazy.nvim/compare/v11.5.2...v11.6.0) (2024-06-29)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **task:** build procs can now yield a LazyMsg for more control ([9cf7459](https://github.com/folke/lazy.nvim/commit/9cf745939d792204a18d7ad10a54d22386ececf3))
|
|
||||||
|
|
||||||
## [11.5.2](https://github.com/folke/lazy.nvim/compare/v11.5.1...v11.5.2) (2024-06-28)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **git:** tagrefs ([2a6a2dc](https://github.com/folke/lazy.nvim/commit/2a6a2dce1b14f35e7eb7cbe8f25202ed83cba697))
|
|
||||||
|
|
||||||
## [11.5.1](https://github.com/folke/lazy.nvim/compare/v11.5.0...v11.5.1) (2024-06-28)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **rocks:** lua-5.1. Closes [#1575](https://github.com/folke/lazy.nvim/issues/1575) ([4319846](https://github.com/folke/lazy.nvim/commit/4319846b8c8a05975c4139b0bc9f7e6e7a9e6e21))
|
|
||||||
* **task:** run on_exit async. See [#1569](https://github.com/folke/lazy.nvim/issues/1569) ([60fe75c](https://github.com/folke/lazy.nvim/commit/60fe75c88db22025989600bb53dba247654d9ed5))
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* async render ([ab46edb](https://github.com/folke/lazy.nvim/commit/ab46edbd47fa9f380db65dbf0a7c35d18d810b19))
|
|
||||||
* use timer instead of check for async executor ([f85575a](https://github.com/folke/lazy.nvim/commit/f85575ab23c81eb897fb2cb1240a0fa1cb41f7f4))
|
|
||||||
|
|
||||||
## [11.5.0](https://github.com/folke/lazy.nvim/compare/v11.4.2...v11.5.0) (2024-06-27)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* added `opts.headless` to control ansi output when running headless ([a0a51c0](https://github.com/folke/lazy.nvim/commit/a0a51c06c2fcddda925667142516c89777eb0c8e))
|
|
||||||
* added localleader-i to inspect a plugin ([2e1167d](https://github.com/folke/lazy.nvim/commit/2e1167df4ab055e8327317ac38210b111cbaec83))
|
|
||||||
* **health:** show steps to get luarocks working. See [#1570](https://github.com/folke/lazy.nvim/issues/1570) ([c0fd59b](https://github.com/folke/lazy.nvim/commit/c0fd59b020dc4efb91b226b0bbc4a22f28c12321))
|
|
||||||
* **health:** show user's lazy.nvim version in checkhealth ([9c8e7a4](https://github.com/folke/lazy.nvim/commit/9c8e7a48406109458370f3b52f6f058943db40f4))
|
|
||||||
* **ui:** keep cursor position when rendering view ([591ded8](https://github.com/folke/lazy.nvim/commit/591ded8309e45806ae3fb58b7b68fe58785a3ada))
|
|
||||||
* **ui:** remap gx -> K. Fixes [#1561](https://github.com/folke/lazy.nvim/issues/1561) ([e3e4314](https://github.com/folke/lazy.nvim/commit/e3e431480d6c9ab460cf08b1e35311c2ab2c05c4))
|
|
||||||
* **ui:** show indication of plugins that need build. See [#1563](https://github.com/folke/lazy.nvim/issues/1563) ([53f314d](https://github.com/folke/lazy.nvim/commit/53f314d9e6ef594677acdf5f038a4a042a7f3e38))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **manage:** dont skip install for plugins that need a build, but dont have an url (like local plugins). Fixes [#1563](https://github.com/folke/lazy.nvim/issues/1563) ([a0391c3](https://github.com/folke/lazy.nvim/commit/a0391c3e21e063df9dee70f17ae7891497cdcec9))
|
|
||||||
* **meta:** resolve deps from meta instead of fragments. Fixes [#1566](https://github.com/folke/lazy.nvim/issues/1566) ([6a42327](https://github.com/folke/lazy.nvim/commit/6a423278a10ff7b1a76795275111d01632851c48))
|
|
||||||
* **pkg:** only show pkg changed when effectively changing a pkg file. Fixes [#1567](https://github.com/folke/lazy.nvim/issues/1567) ([24a86d5](https://github.com/folke/lazy.nvim/commit/24a86d5ca4652a77f0f2c78dd7c693a3c369ab68))
|
|
||||||
* **rocks:** if installing with luarocks (binaries) fails, then build from source. Fixes [#1563](https://github.com/folke/lazy.nvim/issues/1563) ([8227632](https://github.com/folke/lazy.nvim/commit/82276321f5132c680a852bec0bb9b55694ab2a21))
|
|
||||||
* **runner:** only check for errors when a task is no longer running ([e02c5b1](https://github.com/folke/lazy.nvim/commit/e02c5b1b5787210dfbf89681d94e7861b30aa139))
|
|
||||||
* **runner:** only use Config.plugins when updated. Fixes [#1560](https://github.com/folke/lazy.nvim/issues/1560) ([97f4df0](https://github.com/folke/lazy.nvim/commit/97f4df0824da13b2b0d065f0dc43c49862581a01))
|
|
||||||
* **runner:** properly do concurrency ([66a4170](https://github.com/folke/lazy.nvim/commit/66a4170f0e9ab238972f73a268582cf65026a017))
|
|
||||||
* **runner:** wait_step ([93b3a77](https://github.com/folke/lazy.nvim/commit/93b3a77286c4212850e21a6b3e31d328b5a86df4))
|
|
||||||
* **ui:** diagnostics without status ([249902a](https://github.com/folke/lazy.nvim/commit/249902ab3194226efec0dbc3e000e758c43b4714))
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* prevent active waiting in coroutines. suspend/resume instead ([68cee30](https://github.com/folke/lazy.nvim/commit/68cee30cdb1f7a29d10b44b00506aafa092b6cee))
|
|
||||||
|
|
||||||
## [11.4.2](https://github.com/folke/lazy.nvim/compare/v11.4.1...v11.4.2) (2024-06-26)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **config:** dont start checker/change_detection when running headless ([2aa8e06](https://github.com/folke/lazy.nvim/commit/2aa8e061f22579b0cabc74f05a90f7344d92195c))
|
|
||||||
* **git:** fetch commit from origin or local to check if branch was changed. See [#1549](https://github.com/folke/lazy.nvim/issues/1549) ([28e435b](https://github.com/folke/lazy.nvim/commit/28e435b7f34eecd8b90bc87ac71c70b79fcb03b3))
|
|
||||||
* **rocks:** build.type instead of build.build_type ([aa1c957](https://github.com/folke/lazy.nvim/commit/aa1c9572aa1916e582f9b9c3d43e272b4f23b326))
|
|
||||||
* **rockspec:** dont lazy-load rock deps ([4733611](https://github.com/folke/lazy.nvim/commit/473361139cc05936cd5afb08ab68e5bee1ebb5b3))
|
|
||||||
* **runner:** bring concurrency back ([56075b5](https://github.com/folke/lazy.nvim/commit/56075b57c421fc5e751c1da7a7f1bf18ec1499a7))
|
|
||||||
* **ui:** don't show output when it's the same as error ([e79805d](https://github.com/folke/lazy.nvim/commit/e79805d706f815a62467260cb307844c368c3dba))
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* tasks are now fully async ([0614ca6](https://github.com/folke/lazy.nvim/commit/0614ca6ca629704cb1846c0d6f9a250b526900b9))
|
|
||||||
* **util:** improve impl of throttle ([3695215](https://github.com/folke/lazy.nvim/commit/36952153ecb5b196c74e2d9a28eb0e01a9eb02fe))
|
|
||||||
|
|
||||||
## [11.4.1](https://github.com/folke/lazy.nvim/compare/v11.4.0...v11.4.1) (2024-06-25)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **health:** show what plugins need luarocks and if none, use warnings instead of errors. See [#1551](https://github.com/folke/lazy.nvim/issues/1551) ([0d9fd63](https://github.com/folke/lazy.nvim/commit/0d9fd636beb9e3783edcdba2b31932280bdc05f7))
|
|
||||||
|
|
||||||
## [11.4.0](https://github.com/folke/lazy.nvim/compare/v11.3.0...v11.4.0) (2024-06-25)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **pkg:** utils to get rock to url mappings ([be74a8a](https://github.com/folke/lazy.nvim/commit/be74a8a535fea6a480143fb52b4d6958d9e2da94))
|
|
||||||
* **rocks:** simple rockspecs are now fully resolved by lazy without luarocks. See [#1548](https://github.com/folke/lazy.nvim/issues/1548) ([6b8bf58](https://github.com/folke/lazy.nvim/commit/6b8bf58ebf9114f8f31fb78cbf057e452cb0e540))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **meta:** only tag new top-level pkg fragment as optional ([25981e1](https://github.com/folke/lazy.nvim/commit/25981e1f3927ee0b22aefea122ebac1cddafdca6))
|
|
||||||
|
|
||||||
## [11.3.0](https://github.com/folke/lazy.nvim/compare/v11.2.1...v11.3.0) (2024-06-25)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **rocks:** use hererocks to install luarocks when luarocks is not found ([d87da76](https://github.com/folke/lazy.nvim/commit/d87da7667939deff2ed8b5a3c198d9ea2e03fee4))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **fragments:** check for empty plugin names ([dea1f68](https://github.com/folke/lazy.nvim/commit/dea1f687fe6e15eb3098557a69d44231ebcb6cf5))
|
|
||||||
* **meta:** no need to check for old_dir when frags were not built yet. Fixes [#1550](https://github.com/folke/lazy.nvim/issues/1550) ([24c8322](https://github.com/folke/lazy.nvim/commit/24c832213c505a0d7ca021c0e14bba43e0fef75c))
|
|
||||||
* **rocks:** better errors / warnings when something goes wrong with luarocks ([7d3f691](https://github.com/folke/lazy.nvim/commit/7d3f69104fb39d3e6e12f808204b3a7b38f86916))
|
|
||||||
* **rocks:** hererocks paths on windows ([45cd8d3](https://github.com/folke/lazy.nvim/commit/45cd8d3f0fab197e6e0391cffa38879bdda4c2cd))
|
|
||||||
* **rocks:** windows ([4ca3e9a](https://github.com/folke/lazy.nvim/commit/4ca3e9aa51c03dda73b40ec9901deac5d4f11c69))
|
|
||||||
|
|
||||||
## [11.2.1](https://github.com/folke/lazy.nvim/compare/v11.2.0...v11.2.1) (2024-06-24)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **loader:** no need to check plugin.dir in auto_load ([62a47b9](https://github.com/folke/lazy.nvim/commit/62a47b921fbffb3c1c8088a731029ae234f98851))
|
|
||||||
|
|
||||||
## [11.2.0](https://github.com/folke/lazy.nvim/compare/v11.1.0...v11.2.0) (2024-06-24)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* rewrite some known plugins to lazy specs instead of luarocks (plenary.nvim). Closes [#1540](https://github.com/folke/lazy.nvim/issues/1540) ([a089d43](https://github.com/folke/lazy.nvim/commit/a089d43dba7438532c56e1c582c5974713bd48f8))
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* minimize meta rebuild when loading specs ([1446f6c](https://github.com/folke/lazy.nvim/commit/1446f6cfbb4ca0a7ee0baf3acc86ab5e4be5ab22))
|
|
||||||
|
|
||||||
## [11.1.0](https://github.com/folke/lazy.nvim/compare/v11.0.1...v11.1.0) (2024-06-24)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* make it easier to disable luarocks ([07c067a](https://github.com/folke/lazy.nvim/commit/07c067a1a82bb0988179e1887bba9df4721b3ea7))
|
|
||||||
* show rockspec deps in plugin details ([656d3d1](https://github.com/folke/lazy.nvim/commit/656d3d1f5b5910e50af3d67286999ff7088ebfb6))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **health:** added luarocks check to health ([0f45c0d](https://github.com/folke/lazy.nvim/commit/0f45c0d0623b4850716898a5e399c844466690f6))
|
|
||||||
* **health:** only check for luarocks when luarocks is enabled. ([ae4881d](https://github.com/folke/lazy.nvim/commit/ae4881d36e7f589124f8eb7febfc6a8b58f8e027))
|
|
||||||
* **health:** show missing luarocks as warning ([e3ee51b](https://github.com/folke/lazy.nvim/commit/e3ee51b6680a116649da56f6c651d53c3e47be4e))
|
|
||||||
* **runner:** sync package specs after installing and before building ([105d480](https://github.com/folke/lazy.nvim/commit/105d4805ad58875d0b0fafe1185679539b8bc69a))
|
|
||||||
|
|
||||||
## [11.0.1](https://github.com/folke/lazy.nvim/compare/v11.0.0...v11.0.1) (2024-06-24)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **rocks:** dont trigger rebuild for luarocks when build is overriden ([146de4e](https://github.com/folke/lazy.nvim/commit/146de4e801f9169e79052a51365eaae789094611))
|
|
||||||
|
|
||||||
## [11.0.0](https://github.com/folke/lazy.nvim/compare/v10.24.3...v11.0.0) (2024-06-24)
|
|
||||||
|
|
||||||
|
|
||||||
### ⚠ BREAKING CHANGES
|
|
||||||
|
|
||||||
* new docs for v11.0
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* added support for plugin packages by lazy, rockspec and packspec ([3be55a4](https://github.com/folke/lazy.nvim/commit/3be55a46158cde17e2b853e531d260f3738a5346))
|
|
||||||
* **build:** build files and functions are now async. use coroutine.yield to interrupt and report progress ([368747b](https://github.com/folke/lazy.nvim/commit/368747bc9a314b4f0745547ebdcc3fbc4d100c0a))
|
|
||||||
* luarocks support ([f1ba2e3](https://github.com/folke/lazy.nvim/commit/f1ba2e3d057ae5c03d04134a9d538d0b2251f13b))
|
|
||||||
* **meta:** check for dir changes for plugins already added to the rtp ([ee2ca39](https://github.com/folke/lazy.nvim/commit/ee2ca39f672a2d6f4cbb683b525e6b3d91f3fc0c))
|
|
||||||
* new docs for v11.0 ([183f59e](https://github.com/folke/lazy.nvim/commit/183f59e2e85dea0c38ed7d16c7c7e543c0b739c7))
|
|
||||||
* packspec ([8eba74c](https://github.com/folke/lazy.nvim/commit/8eba74c3fc41e1a364225f744022f8b3ff11d796))
|
|
||||||
* **pkg:** import package specs in the scope of the plugin ([c1912e2](https://github.com/folke/lazy.nvim/commit/c1912e23481ba72a8d8f7a5c736f5e2547e6853e))
|
|
||||||
* rewrite of spec resolving ([75ffe56](https://github.com/folke/lazy.nvim/commit/75ffe56f70faac43f077796b91178d2f1419f8ce))
|
|
||||||
* spec.rocks is no longer needed & added support for installing any luarock ([fcfd548](https://github.com/folke/lazy.nvim/commit/fcfd54835da5af64c6046060f4db62c4626d209c))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **fragments:** prevent adding the same spec instance more than once ([dbffad6](https://github.com/folke/lazy.nvim/commit/dbffad6f44674a3c1b23c649a0abab299d7349d8))
|
|
||||||
* **luarocks:** cleanup luarocks when deleting a plugin ([b73c57e](https://github.com/folke/lazy.nvim/commit/b73c57ed9ec8e63bbb867d21a3f3a865224b25d4))
|
|
||||||
* **pkg:** automatically update pkgs when editing a pkg file ([7b6ddbf](https://github.com/folke/lazy.nvim/commit/7b6ddbfc137ad5d8b178a3bbf5a1338630f30625))
|
|
||||||
* **pkg:** correctly pre-load package specs and remove them when needed during resolve ([4326d4b](https://github.com/folke/lazy.nvim/commit/4326d4b487d4facc19b375ca30cd633cf56d88ed))
|
|
||||||
* **pkg:** make sure state dir exists ([3515cb5](https://github.com/folke/lazy.nvim/commit/3515cb518f61c02b41cd3a8d8135c9a5862a982f))
|
|
||||||
* **pkg:** versioning and reload specs when pkg-cache is dirty ([fd8229d](https://github.com/folke/lazy.nvim/commit/fd8229d6e312e83d6bafda256adf0e650b13ca01))
|
|
||||||
* **rocks:** only build rockspec when it has deps or an advanced build step ([9a6c219](https://github.com/folke/lazy.nvim/commit/9a6c21982638b6e2ea498514baee9186c0e60d82))
|
|
||||||
|
|
||||||
## [10.24.3](https://github.com/folke/lazy.nvim/compare/v10.24.2...v10.24.3) (2024-06-23)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **util:** dump ([025520d](https://github.com/folke/lazy.nvim/commit/025520d083c61baa7cd1f45807f5fe1ac9fbb50d))
|
|
||||||
|
|
||||||
## [10.24.2](https://github.com/folke/lazy.nvim/compare/v10.24.1...v10.24.2) (2024-06-16)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **plugin:** rebuild optional when needed and remove frags from parent deps. Fixes [#1402](https://github.com/folke/lazy.nvim/issues/1402) ([b4316da](https://github.com/folke/lazy.nvim/commit/b4316da7310682144c279c5f0451e59ee5f6c9d1))
|
|
||||||
|
|
||||||
## [10.24.1](https://github.com/folke/lazy.nvim/compare/v10.24.0...v10.24.1) (2024-06-16)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **plugin:** better way of dealing with local specs. Fixes [#1524](https://github.com/folke/lazy.nvim/issues/1524) ([be5dfba](https://github.com/folke/lazy.nvim/commit/be5dfba54216ccb80959df24d48540f07ee127a3))
|
|
||||||
|
|
||||||
## [10.24.0](https://github.com/folke/lazy.nvim/compare/v10.23.0...v10.24.0) (2024-06-15)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* find local_spec in parent directories as well. Closes [#1519](https://github.com/folke/lazy.nvim/issues/1519) ([e2e10d9](https://github.com/folke/lazy.nvim/commit/e2e10d9cbe133265ccdcc44cafa7c10773d96837))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **plugin:** check optional plugins again after resolving enabled. Fixes [#1402](https://github.com/folke/lazy.nvim/issues/1402) ([067fd41](https://github.com/folke/lazy.nvim/commit/067fd41933c9f59eb3445eb942052c651a4c9a62))
|
|
||||||
|
|
||||||
## [10.23.0](https://github.com/folke/lazy.nvim/compare/v10.22.2...v10.23.0) (2024-06-07)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **plugin:** `opts_extend` can be a list of dotted keys that will be extended instead of merged ([1f7b720](https://github.com/folke/lazy.nvim/commit/1f7b720cffa6d8f00ebb040bc60e8e056e0a6002))
|
|
||||||
* **util:** opts merging now supports lists extending by tagging a table with __extend = true. Use with care ([74fd361](https://github.com/folke/lazy.nvim/commit/74fd3611f291a2506c5534109689bb7b028f0566))
|
|
||||||
|
|
||||||
## [10.22.2](https://github.com/folke/lazy.nvim/compare/v10.22.1...v10.22.2) (2024-06-06)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **keys:** buffer-local nop mappings ([ff90417](https://github.com/folke/lazy.nvim/commit/ff904178089582f90fdc625493f3d3bddbefd6ea))
|
|
||||||
* **keys:** never lazy-load `<nop>` or empty rhs keymaps ([3e4c795](https://github.com/folke/lazy.nvim/commit/3e4c795cec32481bc6d0b30c05125fdf7ef2d412))
|
|
||||||
|
|
||||||
## [10.22.1](https://github.com/folke/lazy.nvim/compare/v10.22.0...v10.22.1) (2024-06-02)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* force new release ([9242edb](https://github.com/folke/lazy.nvim/commit/9242edb73939e7508dbd827e9c013579391f0668))
|
|
||||||
|
|
||||||
## [10.22.0](https://github.com/folke/lazy.nvim/compare/v10.21.2...v10.22.0) (2024-06-01)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* set `vim.env.LAZY` to lazy root ([6a141a6](https://github.com/folke/lazy.nvim/commit/6a141a6dbb6f6b5495ef6716c0dce898546d7b2c))
|
|
||||||
|
|
||||||
## [10.21.2](https://github.com/folke/lazy.nvim/compare/v10.21.1...v10.21.2) (2024-05-31)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **ui:** deduplicate plugins when selecting multiple ([#1491](https://github.com/folke/lazy.nvim/issues/1491)) ([b77aaa0](https://github.com/folke/lazy.nvim/commit/b77aaa08cb5b178ed8662765caa41c70ff254a4c))
|
|
||||||
|
|
||||||
## [10.21.1](https://github.com/folke/lazy.nvim/compare/v10.21.0...v10.21.1) (2024-05-31)
|
## [10.21.1](https://github.com/folke/lazy.nvim/compare/v10.21.0...v10.21.1) (2024-05-31)
|
||||||
|
|
||||||
|
|
||||||
|
|
847
README.md
847
README.md
|
@ -1,36 +1,4 @@
|
||||||
<h4 align="center">
|
# 💤 lazy.nvim
|
||||||
<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.
|
**lazy.nvim** is a modern plugin manager for Neovim.
|
||||||
|
|
||||||
|
@ -61,9 +29,814 @@
|
||||||
- Neovim >= **0.8.0** (needs to be built with **LuaJIT**)
|
- Neovim >= **0.8.0** (needs to be built with **LuaJIT**)
|
||||||
- Git >= **2.19.0** (for partial clones support)
|
- Git >= **2.19.0** (for partial clones support)
|
||||||
- a [Nerd Font](https://www.nerdfonts.com/) **_(optional)_**
|
- 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.
|
|
||||||
|
|
||||||
## 🚀 Getting Started
|
## 📦 Installation
|
||||||
|
|
||||||
Check the [documentation website](https://lazy.folke.io/) for more information.
|
You can add the following Lua code to your `init.lua` to bootstrap **lazy.nvim**:
|
||||||
|
|
||||||
|
<!-- bootstrap:start -->
|
||||||
|
|
||||||
|
```lua
|
||||||
|
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",
|
||||||
|
"https://github.com/folke/lazy.nvim.git",
|
||||||
|
"--branch=stable", -- latest stable release
|
||||||
|
lazypath,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
vim.opt.rtp:prepend(lazypath)
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- bootstrap:end -->
|
||||||
|
|
||||||
|
Next step is to add **lazy.nvim** below the code added in the prior step in `init.lua`:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
require("lazy").setup(plugins, opts)
|
||||||
|
```
|
||||||
|
|
||||||
|
- **plugins**: this should be a `table` or a `string`
|
||||||
|
- `table`: a list with your [Plugin Spec](#-plugin-spec)
|
||||||
|
- `string`: a Lua module name that contains your [Plugin Spec](#-plugin-spec). See [Structuring Your Plugins](#-structuring-your-plugins)
|
||||||
|
- **opts**: see [Configuration](#%EF%B8%8F-configuration) **_(optional)_**
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- Example using a list of specs with the default options
|
||||||
|
vim.g.mapleader = " " -- Make sure to set `mapleader` before lazy so your mappings are correct
|
||||||
|
vim.g.maplocalleader = "\\" -- Same for `maplocalleader`
|
||||||
|
|
||||||
|
require("lazy").setup({
|
||||||
|
"folke/which-key.nvim",
|
||||||
|
{ "folke/neoconf.nvim", cmd = "Neoconf" },
|
||||||
|
"folke/neodev.nvim",
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
ℹ️ It is recommended to run `:checkhealth lazy` after installation.
|
||||||
|
|
||||||
|
## 🔌 Plugin Spec
|
||||||
|
|
||||||
|
| Property | Type | Description |
|
||||||
|
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| **[1]** | `string?` | Short plugin url. Will be expanded using `config.git.url_format` |
|
||||||
|
| **dir** | `string?` | A directory pointing to a local plugin |
|
||||||
|
| **url** | `string?` | A custom git url where the plugin is hosted |
|
||||||
|
| **name** | `string?` | A custom name for the plugin used for the local plugin directory and as the display name |
|
||||||
|
| **dev** | `boolean?` | When `true`, a local plugin directory will be used instead. See `config.dev` |
|
||||||
|
| **lazy** | `boolean?` | When `true`, the plugin will only be loaded when needed. Lazy-loaded plugins are automatically loaded when their Lua modules are `required`, or when one of the lazy-loading handlers triggers |
|
||||||
|
| **enabled** | `boolean?` or `fun():boolean` | When `false`, or if the `function` returns false, then this plugin will not be included in the spec |
|
||||||
|
| **cond** | `boolean?` or `fun(LazyPlugin):boolean` | When `false`, or if the `function` returns false, then this plugin will not be loaded. Useful to disable some plugins in vscode, or firenvim for example. |
|
||||||
|
| **dependencies** | `LazySpec[]` | A list of plugin names or plugin specs that should be loaded when the plugin loads. Dependencies are always lazy-loaded unless specified otherwise. When specifying a name, make sure the plugin spec has been defined somewhere else. |
|
||||||
|
| **init** | `fun(LazyPlugin)` | `init` functions are always executed during startup |
|
||||||
|
| **opts** | `table` or `fun(LazyPlugin, opts:table)` | `opts` should be a table (will be merged with parent specs), return a table (replaces parent specs) or should change a table. The table will be passed to the `Plugin.config()` function. Setting this value will imply `Plugin.config()` |
|
||||||
|
| **config** | `fun(LazyPlugin, opts:table)` or `true` | `config` is executed when the plugin loads. The default implementation will automatically run `require(MAIN).setup(opts)` if `opts` or `config = true` is set. Lazy uses several heuristics to determine the plugin's `MAIN` module automatically based on the plugin's **name**. See also `opts`. To use the default implementation without `opts` set `config` to `true`. |
|
||||||
|
| **main** | `string?` | You can specify the `main` module to use for `config()` and `opts()`, in case it can not be determined automatically. See `config()` |
|
||||||
|
| **build** | `fun(LazyPlugin)` or `string` or a list of build commands | `build` is executed when a plugin is installed or updated. Before running `build`, a plugin is first loaded. If it's a string it will be ran as a shell command. When prefixed with `:` it is a Neovim command. You can also specify a list to executed multiple build commands. Some plugins provide their own `build.lua` which is automatically used by lazy. So no need to specify a build step for those plugins. |
|
||||||
|
| **branch** | `string?` | Branch of the repository |
|
||||||
|
| **tag** | `string?` | Tag of the repository |
|
||||||
|
| **commit** | `string?` | Commit of the repository |
|
||||||
|
| **version** | `string?` or `false` to override the default | Version to use from the repository. Full [Semver](https://devhints.io/semver) ranges are supported |
|
||||||
|
| **pin** | `boolean?` | When `true`, this plugin will not be included in updates |
|
||||||
|
| **submodules** | `boolean?` | When false, git submodules will not be fetched. Defaults to `true` |
|
||||||
|
| **event** | `string?` or `string[]` or `fun(self:LazyPlugin, event:string[]):string[]` or `{event:string[]\|string, pattern?:string[]\|string}` | Lazy-load on event. Events can be specified as `BufEnter` or with a pattern like `BufEnter *.lua` |
|
||||||
|
| **cmd** | `string?` or `string[]` or `fun(self:LazyPlugin, cmd:string[]):string[]` | Lazy-load on command |
|
||||||
|
| **ft** | `string?` or `string[]` or `fun(self:LazyPlugin, ft:string[]):string[]` | Lazy-load on filetype |
|
||||||
|
| **keys** | `string?` or `string[]` or `LazyKeysSpec[]` or `fun(self:LazyPlugin, keys:string[]):(string \| LazyKeysSpec)[]` | Lazy-load on key mapping |
|
||||||
|
| **module** | `false?` | Do not automatically load this Lua module when it's required somewhere |
|
||||||
|
| **priority** | `number?` | Only useful for **start** plugins (`lazy=false`) to force loading certain plugins first. Default priority is `50`. It's recommended to set this to a high number for colorschemes. |
|
||||||
|
| **optional** | `boolean?` | When a spec is tagged optional, it will only be included in the final spec, when the same plugin has been specified at least once somewhere else without `optional`. This is mainly useful for Neovim distros, to allow setting options on plugins that may/may not be part of the user's plugins |
|
||||||
|
|
||||||
|
### Lazy Loading
|
||||||
|
|
||||||
|
**lazy.nvim** automagically lazy-loads Lua modules, so it is not needed to
|
||||||
|
specify `module=...` everywhere in your plugin specification. This means that if
|
||||||
|
you have a plugin `A` that is lazy-loaded and a plugin `B` that requires a
|
||||||
|
module of plugin `A`, then plugin `A` will be loaded on demand as expected.
|
||||||
|
|
||||||
|
If you don't want this behavior for a certain plugin, you can specify that with `module=false`.
|
||||||
|
You can then manually load the plugin with `:Lazy load foobar.nvim`.
|
||||||
|
|
||||||
|
You can configure **lazy.nvim** to lazy-load all plugins by default with `config.defaults.lazy = true`.
|
||||||
|
|
||||||
|
Additionally, you can also lazy-load on **events**, **commands**,
|
||||||
|
**file types** and **key mappings**.
|
||||||
|
|
||||||
|
Plugins will be lazy-loaded when one of the following is `true`:
|
||||||
|
|
||||||
|
- The plugin only exists as a dependency in your spec
|
||||||
|
- It has an `event`, `cmd`, `ft` or `keys` key
|
||||||
|
- `config.defaults.lazy == true`
|
||||||
|
|
||||||
|
#### 🌈 Colorschemes
|
||||||
|
|
||||||
|
Colorscheme plugins can be configured with `lazy=true`. The plugin will automagically load
|
||||||
|
when doing `colorscheme foobar`.
|
||||||
|
|
||||||
|
> **NOTE:** since **start** plugins can possibly change existing highlight groups,
|
||||||
|
> it's important to make sure that your main **colorscheme** is loaded first.
|
||||||
|
> To ensure this you can use the `priority=1000` field. **_(see the examples)_**
|
||||||
|
|
||||||
|
#### ⌨️ Lazy Key Mappings
|
||||||
|
|
||||||
|
The `keys` property can be a `string` or `string[]` for simple normal-mode mappings, or it
|
||||||
|
can be a `LazyKeysSpec` table with the following key-value pairs:
|
||||||
|
|
||||||
|
- **[1]**: (`string`) lhs **_(required)_**
|
||||||
|
- **[2]**: (`string|fun()`) rhs **_(optional)_**
|
||||||
|
- **mode**: (`string|string[]`) mode **_(optional, defaults to `"n"`)_**
|
||||||
|
- **ft**: (`string|string[]`) `filetype` for buffer-local keymaps **_(optional)_**
|
||||||
|
- any other option valid for `vim.keymap.set`
|
||||||
|
|
||||||
|
Key mappings will load the plugin the first time they get executed.
|
||||||
|
|
||||||
|
When `[2]` is `nil`, then the real mapping has to be created by the `config()` function.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- Example for neo-tree.nvim
|
||||||
|
{
|
||||||
|
"nvim-neo-tree/neo-tree.nvim",
|
||||||
|
keys = {
|
||||||
|
{ "<leader>ft", "<cmd>Neotree toggle<cr>", desc = "NeoTree" },
|
||||||
|
},
|
||||||
|
config = function()
|
||||||
|
require("neo-tree").setup()
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Versioning
|
||||||
|
|
||||||
|
If you want to install a specific revision of a plugin, you can use `commit`,
|
||||||
|
`tag`, `branch`, `version`.
|
||||||
|
|
||||||
|
The `version` property supports [Semver](https://semver.org/) ranges.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Click to see some examples</summary>
|
||||||
|
|
||||||
|
- `*`: latest stable version (this excludes pre-release versions)
|
||||||
|
- `1.2.x`: any version that starts with `1.2`, such as `1.2.0`, `1.2.3`, etc.
|
||||||
|
- `^1.2.3`: any version that is compatible with `1.2.3`, such as `1.3.0`, `1.4.5`, etc., but not `2.0.0`.
|
||||||
|
- `~1.2.3`: any version that is compatible with `1.2.3`, such as `1.2.4`, `1.2.5`, but not `1.3.0`.
|
||||||
|
- `>1.2.3`: any version that is greater than `1.2.3`, such as `1.3.0`, `1.4.5`, etc.
|
||||||
|
- `>=1.2.3`: any version that is greater than or equal to `1.2.3`, such as `1.2.3`, `1.3.0`, `1.4.5`, etc.
|
||||||
|
- `<1.2.3`: any version that is less than `1.2.3`, such as `1.1.0`, `1.0.5`, etc.
|
||||||
|
- `<=1.2.3`: any version that is less than or equal to `1.2.3`, such as `1.2.3`, `1.1.0`, `1.0.5`, etc
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
You can set `config.defaults.version = "*"` to install the latest stable
|
||||||
|
version of plugins that support Semver.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
<!-- spec:start -->
|
||||||
|
|
||||||
|
```lua
|
||||||
|
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 configure 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 },
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- spec:end -->
|
||||||
|
|
||||||
|
## ⚙️ Configuration
|
||||||
|
|
||||||
|
**lazy.nvim** comes with the following defaults:
|
||||||
|
|
||||||
|
<!-- config:start -->
|
||||||
|
|
||||||
|
```lua
|
||||||
|
{
|
||||||
|
root = vim.fn.stdpath("data") .. "/lazy", -- directory where plugins will be installed
|
||||||
|
defaults = {
|
||||||
|
lazy = false, -- should plugins be lazy-loaded?
|
||||||
|
version = nil,
|
||||||
|
-- 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
|
||||||
|
-- version = "*", -- enable this to try installing the latest stable versions of plugins
|
||||||
|
},
|
||||||
|
-- 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,
|
||||||
|
},
|
||||||
|
dev = {
|
||||||
|
---@type string | fun(plugin: LazyPlugin): string directory where you store your local plugin projects
|
||||||
|
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 = "",
|
||||||
|
event = " ",
|
||||||
|
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 = 20, -- 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>t"] = {
|
||||||
|
function(plugin)
|
||||||
|
require("lazy.util").float_term(nil, {
|
||||||
|
cwd = plugin.dir,
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
desc = "Open terminal in plugin dir",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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 dont have docs
|
||||||
|
skip_if_doc_exists = true,
|
||||||
|
},
|
||||||
|
state = vim.fn.stdpath("state") .. "/lazy/state.json", -- state info for checker and other things
|
||||||
|
build = {
|
||||||
|
-- Plugins can provide a `build.lua` file that will be executed when the plugin is installed
|
||||||
|
-- or updated. When the plugin spec also has a `build` command, the plugin's `build.lua` not be
|
||||||
|
-- executed. In this case, a warning message will be shown.
|
||||||
|
warn_on_override = true,
|
||||||
|
},
|
||||||
|
-- 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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- config:end -->
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>If you don't want to use a Nerd Font, you can replace the icons with Unicode symbols.</summary>
|
||||||
|
|
||||||
|
```lua
|
||||||
|
{
|
||||||
|
ui = {
|
||||||
|
icons = {
|
||||||
|
cmd = "⌘",
|
||||||
|
config = "🛠",
|
||||||
|
event = "📅",
|
||||||
|
ft = "📂",
|
||||||
|
init = "⚙",
|
||||||
|
keys = "🗝",
|
||||||
|
plugin = "🔌",
|
||||||
|
runtime = "💻",
|
||||||
|
require = "🌙",
|
||||||
|
source = "📄",
|
||||||
|
start = "🚀",
|
||||||
|
task = "📌",
|
||||||
|
lazy = "💤 ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## 🚀 Usage
|
||||||
|
|
||||||
|
Plugins are managed with the `:Lazy` command.
|
||||||
|
Open the help with `<?>` to see all the key mappings.
|
||||||
|
|
||||||
|
You can press `<CR>` on a plugin to show its details. Most properties
|
||||||
|
can be hovered with `<K>` to open links, help files, readmes,
|
||||||
|
git commits and git issues.
|
||||||
|
|
||||||
|
Lazy can automatically check for updates in the background. This feature
|
||||||
|
can be enabled with `config.checker.enabled = true`.
|
||||||
|
|
||||||
|
Any operation can be started from the UI, with a sub command or an API function:
|
||||||
|
|
||||||
|
<!-- commands:start -->
|
||||||
|
|
||||||
|
| Command | Lua | Description |
|
||||||
|
| ------------------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `:Lazy build {plugins}` | `require("lazy").build(opts)` | Rebuild a plugin |
|
||||||
|
| `:Lazy check [plugins]` | `require("lazy").check(opts?)` | Check for updates and show the log (git fetch) |
|
||||||
|
| `:Lazy clean [plugins]` | `require("lazy").clean(opts?)` | Clean plugins that are no longer needed |
|
||||||
|
| `:Lazy clear` | `require("lazy").clear()` | Clear finished tasks |
|
||||||
|
| `:Lazy debug` | `require("lazy").debug()` | Show debug information |
|
||||||
|
| `:Lazy health` | `require("lazy").health()` | Run `:checkhealth lazy` |
|
||||||
|
| `:Lazy help` | `require("lazy").help()` | Toggle this help page |
|
||||||
|
| `:Lazy home` | `require("lazy").home()` | Go back to plugin list |
|
||||||
|
| `:Lazy install [plugins]` | `require("lazy").install(opts?)` | Install missing plugins |
|
||||||
|
| `:Lazy load {plugins}` | `require("lazy").load(opts)` | Load a plugin that has not been loaded yet. Similar to `:packadd`. Like `:Lazy load foo.nvim`. Use `:Lazy! load` to skip `cond` checks. |
|
||||||
|
| `:Lazy log [plugins]` | `require("lazy").log(opts?)` | Show recent updates |
|
||||||
|
| `:Lazy profile` | `require("lazy").profile()` | Show detailed profiling |
|
||||||
|
| `:Lazy reload {plugins}` | `require("lazy").reload(opts)` | Reload a plugin (experimental!!) |
|
||||||
|
| `:Lazy restore [plugins]` | `require("lazy").restore(opts?)` | 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 |
|
||||||
|
| `:Lazy sync [plugins]` | `require("lazy").sync(opts?)` | Run install, clean and update |
|
||||||
|
| `:Lazy update [plugins]` | `require("lazy").update(opts?)` | Update plugins. This will also update the lockfile |
|
||||||
|
|
||||||
|
<!-- commands:end -->
|
||||||
|
|
||||||
|
Any command can have a **bang** to make the command wait till it finished. For example,
|
||||||
|
if you want to sync lazy from the cmdline, you can use:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
nvim --headless "+Lazy! sync" +qa
|
||||||
|
```
|
||||||
|
|
||||||
|
`opts` is a table with the following key-values:
|
||||||
|
|
||||||
|
- **wait**: when true, then the call will wait till the operation completed
|
||||||
|
- **show**: when false, the UI will not be shown
|
||||||
|
- **plugins**: a list of plugin names to run the operation on
|
||||||
|
- **concurrency**: limit the `number` of concurrently running tasks
|
||||||
|
|
||||||
|
Stats API (`require("lazy").stats()`):
|
||||||
|
|
||||||
|
<!-- stats:start -->
|
||||||
|
|
||||||
|
```lua
|
||||||
|
{
|
||||||
|
-- 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 = {},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- stats:end -->
|
||||||
|
|
||||||
|
**lazy.nvim** provides a statusline component that you can use to show the number of pending updates.
|
||||||
|
Make sure to enable `config.checker.enabled = true` to make this work.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Example of configuring <a href="https://github.com/nvim-lualine/lualine.nvim">lualine.nvim</a></summary>
|
||||||
|
|
||||||
|
```lua
|
||||||
|
require("lualine").setup({
|
||||||
|
sections = {
|
||||||
|
lualine_x = {
|
||||||
|
{
|
||||||
|
require("lazy.status").updates,
|
||||||
|
cond = require("lazy.status").has_updates,
|
||||||
|
color = { fg = "#ff9e64" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### 📆 User Events
|
||||||
|
|
||||||
|
The following user events will be triggered:
|
||||||
|
|
||||||
|
- **LazyDone**: when lazy has finished starting up and loaded your config
|
||||||
|
- **LazySync**: after running sync
|
||||||
|
- **LazyInstall**: after an install
|
||||||
|
- **LazyUpdate**: after an update
|
||||||
|
- **LazyClean**: after a clean
|
||||||
|
- **LazyCheck**: after checking for updates
|
||||||
|
- **LazyLog**: after running log
|
||||||
|
- **LazyLoad**: after loading a plugin. The `data` attribute will contain the plugin name.
|
||||||
|
- **LazySyncPre**: before running sync
|
||||||
|
- **LazyInstallPre**: before an install
|
||||||
|
- **LazyUpdatePre**: before an update
|
||||||
|
- **LazyCleanPre**: before a clean
|
||||||
|
- **LazyCheckPre**: before checking for updates
|
||||||
|
- **LazyLogPre**: before running log
|
||||||
|
- **LazyReload**: triggered by change detection after reloading plugin specs
|
||||||
|
- **VeryLazy**: triggered after `LazyDone` and processing `VimEnter` auto commands
|
||||||
|
- **LazyVimStarted**: triggered after `UIEnter` when `require("lazy").stats().startuptime` has been calculated.
|
||||||
|
Useful to update the startuptime on your dashboard.
|
||||||
|
|
||||||
|
## 🔒 Lockfile `lazy-lock.json`
|
||||||
|
|
||||||
|
After every **update**, the local lockfile is updated with the installed revisions.
|
||||||
|
It is recommended to have this file under version control.
|
||||||
|
|
||||||
|
If you use your Neovim config on multiple machines, using the lockfile, you can
|
||||||
|
ensure that the same version of every plugin is installed.
|
||||||
|
|
||||||
|
If you are on another machine, you can do `:Lazy restore`, to update all your plugins to
|
||||||
|
the version from the lockfile.
|
||||||
|
|
||||||
|
## ⚡ Performance
|
||||||
|
|
||||||
|
Great care has been taken to make the startup code (`lazy.core`) as efficient as possible.
|
||||||
|
During startup, all Lua files used before `VimEnter` or `BufReadPre` are byte-compiled and cached,
|
||||||
|
similar to what [impatient.nvim](https://github.com/lewis6991/impatient.nvim) does.
|
||||||
|
|
||||||
|
My config for example loads in about `11ms` with `93` plugins. I do a lot of lazy-loading though :)
|
||||||
|
|
||||||
|
**lazy.nvim** comes with an advanced profiler `:Lazy profile` to help you improve performance.
|
||||||
|
The profiling view shows you why and how long it took to load your plugins.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 🐛 Debug
|
||||||
|
|
||||||
|
See an overview of active lazy-loading handlers and what's in the module cache.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## ▶️ Startup Sequence
|
||||||
|
|
||||||
|
**lazy.nvim** does **NOT** use Neovim packages and even disables plugin loading
|
||||||
|
completely (`vim.go.loadplugins = false`). It takes over the complete
|
||||||
|
startup sequence for more flexibility and better performance.
|
||||||
|
|
||||||
|
In practice this means that step 10 of [Neovim Initialization](https://neovim.io/doc/user/starting.html#initialization) is done by Lazy:
|
||||||
|
|
||||||
|
1. All the plugins' `init()` functions are executed
|
||||||
|
2. All plugins with `lazy=false` are loaded. This includes sourcing `/plugin` and `/ftdetect` files. (`/after` will not be sourced yet)
|
||||||
|
3. All files from `/plugin` and `/ftdetect` directories in your rtp are sourced (excluding `/after`)
|
||||||
|
4. All `/after/plugin` files are sourced (this includes `/after` from plugins)
|
||||||
|
|
||||||
|
Files from runtime directories are always sourced in alphabetical order.
|
||||||
|
|
||||||
|
## 📂 Structuring Your Plugins
|
||||||
|
|
||||||
|
Some users may want to split their plugin specs in multiple files.
|
||||||
|
Instead of passing a spec table to `setup()`, you can use a Lua module.
|
||||||
|
The specs from the **module** and any top-level **sub-modules** will be merged together in the final spec,
|
||||||
|
so it is not needed to add `require` calls in your main plugin file to the other files.
|
||||||
|
|
||||||
|
The benefits of using this approach:
|
||||||
|
|
||||||
|
- Simple to **add** new plugin specs. Just create a new file in your plugins module.
|
||||||
|
- Allows for **caching** of all your plugin specs. This becomes important if you have a lot of smaller plugin specs.
|
||||||
|
- Spec changes will automatically be **reloaded** when they're updated, so the `:Lazy` UI is always up to date.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
- `~/.config/nvim/init.lua`
|
||||||
|
|
||||||
|
```lua
|
||||||
|
require("lazy").setup("plugins")
|
||||||
|
```
|
||||||
|
|
||||||
|
- `~/.config/nvim/lua/plugins.lua` or `~/.config/nvim/lua/plugins/init.lua` **_(this file is optional)_**
|
||||||
|
|
||||||
|
```lua
|
||||||
|
return {
|
||||||
|
"folke/neodev.nvim",
|
||||||
|
"folke/which-key.nvim",
|
||||||
|
{ "folke/neoconf.nvim", cmd = "Neoconf" },
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Any lua file in `~/.config/nvim/lua/plugins/*.lua` will be automatically merged in the main plugin spec
|
||||||
|
|
||||||
|
For a real-life example, you can check [LazyVim](https://github.com/LazyVim/LazyVim) and more specifically:
|
||||||
|
|
||||||
|
- [lazyvim.plugins](https://github.com/LazyVim/LazyVim/tree/main/lua/lazyvim/plugins) contains all the plugin specs that will be loaded
|
||||||
|
|
||||||
|
### ↩️ Importing Specs, `config` & `opts`
|
||||||
|
|
||||||
|
As part of a spec, you can add `import` statements to import additional plugin modules.
|
||||||
|
Both of the `setup()` calls are equivalent:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
require("lazy").setup("plugins")
|
||||||
|
|
||||||
|
-- Same as:
|
||||||
|
require("lazy").setup({{import = "plugins"}})
|
||||||
|
```
|
||||||
|
|
||||||
|
To import multiple modules from a plugin, add additional specs for each import.
|
||||||
|
For example, to import LazyVim core plugins and an optional plugin:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
require("lazy").setup({
|
||||||
|
spec = {
|
||||||
|
{ "LazyVim/LazyVim", import = "lazyvim.plugins" },
|
||||||
|
{ import = "lazyvim.plugins.extras.coding.copilot" },
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
When you import specs, you can override them by simply adding a spec for the same plugin to your local
|
||||||
|
specs, adding any keys you want to override / merge.
|
||||||
|
|
||||||
|
`opts`, `dependencies`, `cmd`, `event`, `ft` and `keys` are always merged with the parent spec.
|
||||||
|
Any other property will override the property from the parent spec.
|
||||||
|
|
||||||
|
## 📦 Migration Guide
|
||||||
|
|
||||||
|
### [packer.nvim](https://github.com/wbthomason/packer.nvim)
|
||||||
|
|
||||||
|
- `setup` ➡️ `init`
|
||||||
|
- `requires` ➡️ `dependencies`
|
||||||
|
- `as` ➡️ `name`
|
||||||
|
- `opt` ➡️ `lazy`
|
||||||
|
- `run` ➡️ `build`
|
||||||
|
- `lock` ➡️ `pin`
|
||||||
|
- `disable=true` ➡️ `enabled = false`
|
||||||
|
- `tag='*'` ➡️ `version="*"`
|
||||||
|
- `after` is **_not needed_** for most use-cases. Use `dependencies` otherwise.
|
||||||
|
- `wants` is **_not needed_** for most use-cases. Use `dependencies` otherwise.
|
||||||
|
- `config` don't support string type, use `fun(LazyPlugin)` instead.
|
||||||
|
- `module` is auto-loaded. No need to specify
|
||||||
|
- `keys` spec is [different](#%EF%B8%8F-lazy-key-mappings)
|
||||||
|
- `rtp` can be accomplished with:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
config = function(plugin)
|
||||||
|
vim.opt.rtp:append(plugin.dir .. "/custom-rtp")
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
With packer `wants`, `requires` and `after` can be used to manage dependencies.
|
||||||
|
With lazy, this isn't needed for most of the Lua dependencies. They can be installed just like normal plugins
|
||||||
|
(even with `lazy=true`) and will be loaded when other plugins need them.
|
||||||
|
The `dependencies` key can be used to group those required plugins with the one that requires them.
|
||||||
|
The plugins which are added as `dependencies` will always be lazy-loaded and loaded when the plugin is loaded.
|
||||||
|
|
||||||
|
### [paq-nvim](https://github.com/savq/paq-nvim)
|
||||||
|
|
||||||
|
- `as` ➡️ `name`
|
||||||
|
- `opt` ➡️ `lazy`
|
||||||
|
- `run` ➡️ `build`
|
||||||
|
|
||||||
|
## ❌ Uninstalling
|
||||||
|
|
||||||
|
To uninstall **lazy.nvim**, you need to remove the following files and directories:
|
||||||
|
|
||||||
|
- **data**: `~/.local/share/nvim/lazy`
|
||||||
|
- **state**: `~/.local/state/nvim/lazy`
|
||||||
|
- **lockfile**: `~/.config/nvim/lazy-lock.json`
|
||||||
|
|
||||||
|
> Paths can differ if you changed `XDG` environment variables.
|
||||||
|
|
||||||
|
## 🌈 Highlight Groups
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Click to see all highlight groups</summary>
|
||||||
|
|
||||||
|
<!-- colors:start -->
|
||||||
|
|
||||||
|
| Highlight Group | Default Group | Description |
|
||||||
|
| --------------------- | -------------------------- | --------------------------------------------------- |
|
||||||
|
| **LazyButton** | **_CursorLine_** | |
|
||||||
|
| **LazyButtonActive** | **_Visual_** | |
|
||||||
|
| **LazyComment** | **_Comment_** | |
|
||||||
|
| **LazyCommit** | **_@variable.builtin_** | commit ref |
|
||||||
|
| **LazyCommitIssue** | **_Number_** | |
|
||||||
|
| **LazyCommitScope** | **_Italic_** | conventional commit scope |
|
||||||
|
| **LazyCommitType** | **_Title_** | conventional commit type |
|
||||||
|
| **LazyDimmed** | **_Conceal_** | property |
|
||||||
|
| **LazyDir** | **_@markup.link_** | directory |
|
||||||
|
| **LazyH1** | **_IncSearch_** | home button |
|
||||||
|
| **LazyH2** | **_Bold_** | titles |
|
||||||
|
| **LazyLocal** | **_Constant_** | |
|
||||||
|
| **LazyNoCond** | **_DiagnosticWarn_** | unloaded icon for a plugin where `cond()` was false |
|
||||||
|
| **LazyNormal** | **_NormalFloat_** | |
|
||||||
|
| **LazyProgressDone** | **_Constant_** | progress bar done |
|
||||||
|
| **LazyProgressTodo** | **_LineNr_** | progress bar todo |
|
||||||
|
| **LazyProp** | **_Conceal_** | property |
|
||||||
|
| **LazyReasonCmd** | **_Operator_** | |
|
||||||
|
| **LazyReasonEvent** | **_Constant_** | |
|
||||||
|
| **LazyReasonFt** | **_Character_** | |
|
||||||
|
| **LazyReasonImport** | **_Identifier_** | |
|
||||||
|
| **LazyReasonKeys** | **_Statement_** | |
|
||||||
|
| **LazyReasonPlugin** | **_Special_** | |
|
||||||
|
| **LazyReasonRequire** | **_@variable.parameter_** | |
|
||||||
|
| **LazyReasonRuntime** | **_@macro_** | |
|
||||||
|
| **LazyReasonSource** | **_Character_** | |
|
||||||
|
| **LazyReasonStart** | **_@variable.member_** | |
|
||||||
|
| **LazySpecial** | **_@punctuation.special_** | |
|
||||||
|
| **LazyTaskError** | **_ErrorMsg_** | task errors |
|
||||||
|
| **LazyTaskOutput** | **_MsgArea_** | task output |
|
||||||
|
| **LazyUrl** | **_@markup.link_** | url |
|
||||||
|
| **LazyValue** | **_@string_** | value of a property |
|
||||||
|
|
||||||
|
<!-- colors:end -->
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## 📚 Plugin Authors
|
||||||
|
|
||||||
|
If your plugin needs a build step, you can create a file `build.lua` or `build/init.lua`
|
||||||
|
in the root of your repo. This file will be loaded when the plugin is installed or updated.
|
||||||
|
|
||||||
|
This makes it easier for users, as they no longer need to specify a `build` command.
|
||||||
|
|
||||||
|
## 📦 Other Neovim Plugin Managers in Lua
|
||||||
|
|
||||||
|
- [pckr.nvim](https://github.com/lewis6991/pckr.nvim)
|
||||||
|
- [packer.nvim](https://github.com/wbthomason/packer.nvim)
|
||||||
|
- [paq-nvim](https://github.com/savq/paq-nvim)
|
||||||
|
- [neopm](https://github.com/ii14/neopm)
|
||||||
|
- [dep](https://github.com/chiyadev/dep)
|
||||||
|
- [optpack.nvim](https://github.com/notomo/optpack.nvim)
|
||||||
|
- [pact.nvim](https://github.com/rktjmp/pact.nvim)
|
||||||
|
|
4
TODO.md
4
TODO.md
|
@ -51,7 +51,7 @@
|
||||||
|
|
||||||
- [ ] add support to specify `engines`, `os` and `cpu` like in `package.json`
|
- [ ] 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
|
- [ ] 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?
|
- default semver merging strategy: if no version matches all, then use highest version?
|
||||||
- [ ] package meta index (package.lua cache for all packages)
|
- [ ] package meta index (package.lua cache for all packages)
|
||||||
|
|
||||||
- [x] document highlight groups
|
- [x] document highlight groups
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
Maybe a quick, "for example, if you have a lua file
|
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
|
`~/.config/nvim/lua/config/plugins.lua` that returns a table" or something it'd
|
||||||
remove most question marks I think.
|
remove most question marks I think.
|
||||||
- [x] When auto-installing the plugins the cursor isn't focused on the floating
|
- [x] When autoinstalling the plugins the cursor isn't focused on the floating
|
||||||
window, but on the non-floating window in the background.
|
window, but on the non-floating window in the background.
|
||||||
- [x] Doing `:Lazy clean` doesn't show which plugins were removed.
|
- [x] Doing `:Lazy clean` doesn't show which plugins were removed.
|
||||||
- [x] Shouldn't the "Versioning" section be in the "Lockfile" chapter?
|
- [x] Shouldn't the "Versioning" section be in the "Lockfile" chapter?
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
-- 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
|
|
1259
doc/lazy.nvim.txt
1259
doc/lazy.nvim.txt
File diff suppressed because it is too large
Load diff
|
@ -1,222 +0,0 @@
|
||||||
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
|
|
|
@ -1,100 +0,0 @@
|
||||||
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
|
@ -1,28 +0,0 @@
|
||||||
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
|
|
|
@ -1,7 +0,0 @@
|
||||||
---@type table<string, LazySpec>
|
|
||||||
return {
|
|
||||||
["plenary.nvim"] = {
|
|
||||||
"nvim-lua/plenary.nvim",
|
|
||||||
lazy = true,
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -8,7 +8,7 @@ local M = {}
|
||||||
---@class ModuleFindOpts
|
---@class ModuleFindOpts
|
||||||
---@field all? boolean Search for all matches (defaults to `false`)
|
---@field all? boolean Search for all matches (defaults to `false`)
|
||||||
---@field rtp? boolean Search for modname in the runtime path (defaults to `true`)
|
---@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 patterns? string[] Paterns to use (defaults to `{"/init.lua", ".lua"}`)
|
||||||
---@field paths? string[] Extra paths to search for modname
|
---@field paths? string[] Extra paths to search for modname
|
||||||
|
|
||||||
---@class ModuleInfo
|
---@class ModuleInfo
|
||||||
|
@ -474,7 +474,7 @@ function Loader.lsmod(path)
|
||||||
return Loader._indexed[path]
|
return Loader._indexed[path]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Debug function that wraps all loaders and tracks stats
|
--- Debug function that wrapps all loaders and tracks stats
|
||||||
---@private
|
---@private
|
||||||
function M._profile_loaders()
|
function M._profile_loaders()
|
||||||
for l, loader in pairs(package.loaders) do
|
for l, loader in pairs(package.loaders) do
|
||||||
|
|
|
@ -7,16 +7,12 @@ local M = {}
|
||||||
M.defaults = {
|
M.defaults = {
|
||||||
root = vim.fn.stdpath("data") .. "/lazy", -- directory where plugins will be installed
|
root = vim.fn.stdpath("data") .. "/lazy", -- directory where plugins will be installed
|
||||||
defaults = {
|
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?
|
lazy = false, -- should plugins be lazy-loaded?
|
||||||
-- It's recommended to leave version=false for now, since a lot the plugin that support versioning,
|
version = nil,
|
||||||
-- 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
|
-- default `cond` you can use to globally disable a lot of plugins
|
||||||
-- when running inside vscode for example
|
-- when running inside vscode for example
|
||||||
cond = nil, ---@type boolean|fun(self:LazyPlugin):boolean|nil
|
cond = nil, ---@type boolean|fun(self:LazyPlugin):boolean|nil
|
||||||
|
-- version = "*", -- enable this to try installing the latest stable versions of plugins
|
||||||
},
|
},
|
||||||
-- leave nil when passing the spec as the first argument to setup()
|
-- leave nil when passing the spec as the first argument to setup()
|
||||||
spec = nil, ---@type LazySpec
|
spec = nil, ---@type LazySpec
|
||||||
|
@ -34,42 +30,9 @@ M.defaults = {
|
||||||
-- then set the below to false. This should work, but is NOT supported and will
|
-- then set the below to false. This should work, but is NOT supported and will
|
||||||
-- increase downloads a lot.
|
-- increase downloads a lot.
|
||||||
filter = true,
|
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",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
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 = {
|
dev = {
|
||||||
-- Directory where you store your local plugin projects. If a function is used,
|
---@type string | fun(plugin: LazyPlugin): string directory where you store your local plugin projects
|
||||||
-- the plugin directory (e.g. `~/projects/plugin-name`) must be returned.
|
|
||||||
---@type string | fun(plugin: LazyPlugin): string
|
|
||||||
path = "~/projects",
|
path = "~/projects",
|
||||||
---@type string[] plugins that match these patterns will use your local versions instead of being fetched from GitHub
|
---@type string[] plugins that match these patterns will use your local versions instead of being fetched from GitHub
|
||||||
patterns = {}, -- For example {"folke"}
|
patterns = {}, -- For example {"folke"}
|
||||||
|
@ -96,7 +59,6 @@ M.defaults = {
|
||||||
icons = {
|
icons = {
|
||||||
cmd = " ",
|
cmd = " ",
|
||||||
config = "",
|
config = "",
|
||||||
debug = "● ",
|
|
||||||
event = " ",
|
event = " ",
|
||||||
favorite = " ",
|
favorite = " ",
|
||||||
ft = " ",
|
ft = " ",
|
||||||
|
@ -122,7 +84,7 @@ M.defaults = {
|
||||||
-- leave nil, to automatically select a browser depending on your OS.
|
-- leave nil, to automatically select a browser depending on your OS.
|
||||||
-- If you want to use a specific browser, you can define it here
|
-- If you want to use a specific browser, you can define it here
|
||||||
browser = nil, ---@type string?
|
browser = nil, ---@type string?
|
||||||
throttle = 1000 / 30, -- how frequently should the ui process render events
|
throttle = 20, -- how frequently should the ui process render events
|
||||||
custom_keys = {
|
custom_keys = {
|
||||||
-- You can define custom key maps here. If present, the description will
|
-- You can define custom key maps here. If present, the description will
|
||||||
-- be shown in the help menu.
|
-- be shown in the help menu.
|
||||||
|
@ -137,16 +99,6 @@ M.defaults = {
|
||||||
desc = "Open lazygit log",
|
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"] = {
|
["<localleader>t"] = {
|
||||||
function(plugin)
|
function(plugin)
|
||||||
require("lazy.util").float_term(nil, {
|
require("lazy.util").float_term(nil, {
|
||||||
|
@ -157,17 +109,6 @@ M.defaults = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
-- 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 = {
|
||||||
-- diff command <d> can be one of:
|
-- diff command <d> can be one of:
|
||||||
-- * browser: opens the github compare view. Note that this is always mapped to <K> as well,
|
-- * browser: opens the github compare view. Note that this is always mapped to <K> as well,
|
||||||
|
@ -219,10 +160,16 @@ M.defaults = {
|
||||||
enabled = true,
|
enabled = true,
|
||||||
root = vim.fn.stdpath("state") .. "/lazy/readme",
|
root = vim.fn.stdpath("state") .. "/lazy/readme",
|
||||||
files = { "README.md", "lua/**/README.md" },
|
files = { "README.md", "lua/**/README.md" },
|
||||||
-- only generate markdown helptags for plugins that don't have docs
|
-- only generate markdown helptags for plugins that dont have docs
|
||||||
skip_if_doc_exists = true,
|
skip_if_doc_exists = true,
|
||||||
},
|
},
|
||||||
state = vim.fn.stdpath("state") .. "/lazy/state.json", -- state info for checker and other things
|
state = vim.fn.stdpath("state") .. "/lazy/state.json", -- state info for checker and other things
|
||||||
|
build = {
|
||||||
|
-- Plugins can provide a `build.lua` file that will be executed when the plugin is installed
|
||||||
|
-- or updated. When the plugin spec also has a `build` command, the plugin's `build.lua` not be
|
||||||
|
-- executed. In this case, a warning message will be shown.
|
||||||
|
warn_on_override = true,
|
||||||
|
},
|
||||||
-- Enable profiling of lazy.nvim. This will add some overhead,
|
-- Enable profiling of lazy.nvim. This will add some overhead,
|
||||||
-- so only enable this when you are debugging lazy.nvim
|
-- so only enable this when you are debugging lazy.nvim
|
||||||
profiling = {
|
profiling = {
|
||||||
|
@ -235,14 +182,7 @@ M.defaults = {
|
||||||
debug = false,
|
debug = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
function M.hererocks()
|
M.version = "10.21.1" -- x-release-please-version
|
||||||
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.ns = vim.api.nvim_create_namespace("lazy")
|
||||||
|
|
||||||
|
@ -267,10 +207,8 @@ M.mapleader = nil
|
||||||
---@type string
|
---@type string
|
||||||
M.maplocalleader = nil
|
M.maplocalleader = nil
|
||||||
|
|
||||||
M.suspended = false
|
|
||||||
|
|
||||||
function M.headless()
|
function M.headless()
|
||||||
return not M.suspended and #vim.api.nvim_list_uis() == 0
|
return #vim.api.nvim_list_uis() == 0
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param opts? LazyConfig
|
---@param opts? LazyConfig
|
||||||
|
@ -282,7 +220,6 @@ function M.setup(opts)
|
||||||
end
|
end
|
||||||
table.insert(M.options.install.colorscheme, "habamax")
|
table.insert(M.options.install.colorscheme, "habamax")
|
||||||
|
|
||||||
-- root
|
|
||||||
M.options.root = Util.norm(M.options.root)
|
M.options.root = Util.norm(M.options.root)
|
||||||
if type(M.options.dev.path) == "string" then
|
if type(M.options.dev.path) == "string" then
|
||||||
M.options.dev.path = Util.norm(M.options.dev.path)
|
M.options.dev.path = Util.norm(M.options.dev.path)
|
||||||
|
@ -298,17 +235,13 @@ function M.setup(opts)
|
||||||
|
|
||||||
M.me = debug.getinfo(1, "S").source:sub(2)
|
M.me = debug.getinfo(1, "S").source:sub(2)
|
||||||
M.me = Util.norm(vim.fn.fnamemodify(M.me, ":p:h:h:h:h"))
|
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
|
if M.options.performance.rtp.reset then
|
||||||
---@type vim.Option
|
|
||||||
vim.opt.rtp = {
|
vim.opt.rtp = {
|
||||||
vim.fn.stdpath("config"),
|
vim.fn.stdpath("config"),
|
||||||
vim.fn.stdpath("data") .. "/site",
|
vim.fn.stdpath("data") .. "/site",
|
||||||
M.me,
|
M.me,
|
||||||
vim.env.VIMRUNTIME,
|
vim.env.VIMRUNTIME,
|
||||||
lib,
|
vim.fn.fnamemodify(vim.v.progpath, ":p:h:h") .. "/lib/nvim",
|
||||||
vim.fn.stdpath("config") .. "/after",
|
vim.fn.stdpath("config") .. "/after",
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -322,6 +255,10 @@ function M.setup(opts)
|
||||||
M.mapleader = vim.g.mapleader
|
M.mapleader = vim.g.mapleader
|
||||||
M.maplocalleader = vim.g.maplocalleader
|
M.maplocalleader = vim.g.maplocalleader
|
||||||
|
|
||||||
|
if M.headless() then
|
||||||
|
require("lazy.view.commands").setup()
|
||||||
|
end
|
||||||
|
|
||||||
vim.api.nvim_create_autocmd("UIEnter", {
|
vim.api.nvim_create_autocmd("UIEnter", {
|
||||||
once = true,
|
once = true,
|
||||||
callback = function()
|
callback = function()
|
||||||
|
@ -329,9 +266,6 @@ function M.setup(opts)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
if M.headless() then
|
|
||||||
require("lazy.view.commands").setup()
|
|
||||||
else
|
|
||||||
vim.api.nvim_create_autocmd("User", {
|
vim.api.nvim_create_autocmd("User", {
|
||||||
pattern = "VeryLazy",
|
pattern = "VeryLazy",
|
||||||
once = true,
|
once = true,
|
||||||
|
@ -345,27 +279,9 @@ function M.setup(opts)
|
||||||
require("lazy.manage.checker").start()
|
require("lazy.manage.checker").start()
|
||||||
end, 10)
|
end, 10)
|
||||||
end
|
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,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
vim.api.nvim_create_autocmd({ "VimSuspend", "VimResume" }, {
|
|
||||||
callback = function(ev)
|
|
||||||
M.suspended = ev.event == "VimSuspend"
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
Util.very_lazy()
|
Util.very_lazy()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,174 +0,0 @@
|
||||||
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
|
|
|
@ -75,9 +75,7 @@ function M:_add(event)
|
||||||
end
|
end
|
||||||
-- HACK: work-around for https://github.com/neovim/neovim/issues/25526
|
-- HACK: work-around for https://github.com/neovim/neovim/issues/25526
|
||||||
done = true
|
done = true
|
||||||
if event.id ~= "VeryLazy" then
|
|
||||||
Util.track({ [self.type] = event.id })
|
Util.track({ [self.type] = event.id })
|
||||||
end
|
|
||||||
|
|
||||||
local state = M.get_state(ev.event, ev.buf, ev.data)
|
local state = M.get_state(ev.event, ev.buf, ev.data)
|
||||||
|
|
||||||
|
@ -88,9 +86,7 @@ function M:_add(event)
|
||||||
for _, s in ipairs(state) do
|
for _, s in ipairs(state) do
|
||||||
M.trigger(s)
|
M.trigger(s)
|
||||||
end
|
end
|
||||||
if event.id ~= "VeryLazy" then
|
|
||||||
Util.track()
|
Util.track()
|
||||||
end
|
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@ local Util = require("lazy.core.util")
|
||||||
---@field type LazyHandlerTypes
|
---@field type LazyHandlerTypes
|
||||||
---@field extends? LazyHandler
|
---@field extends? LazyHandler
|
||||||
---@field active table<string,table<string,string>>
|
---@field active table<string,table<string,string>>
|
||||||
---@field managed table<string,string> mapping handler keys to plugin names
|
---@field managed table<string,string>
|
||||||
---@field super LazyHandler
|
---@field super LazyHandler
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ function M:add(plugin)
|
||||||
if not self.active[key] then
|
if not self.active[key] then
|
||||||
self.active[key] = {}
|
self.active[key] = {}
|
||||||
self:_add(value)
|
self:_add(value)
|
||||||
self.managed[key] = plugin.name
|
self.managed[key] = key
|
||||||
end
|
end
|
||||||
self.active[key][plugin.name] = plugin.name
|
self.active[key][plugin.name] = plugin.name
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,7 +11,7 @@ local Util = require("lazy.core.util")
|
||||||
|
|
||||||
---@class LazyKeysSpec: LazyKeysBase
|
---@class LazyKeysSpec: LazyKeysBase
|
||||||
---@field [1] string lhs
|
---@field [1] string lhs
|
||||||
---@field [2]? string|fun():string?|false rhs
|
---@field [2]? string|fun()|false rhs
|
||||||
---@field mode? string|string[]
|
---@field mode? string|string[]
|
||||||
|
|
||||||
---@class LazyKeys: LazyKeysBase
|
---@class LazyKeys: LazyKeysBase
|
||||||
|
@ -102,11 +102,6 @@ function M.opts(keys)
|
||||||
return opts
|
return opts
|
||||||
end
|
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
|
---@param keys LazyKeys
|
||||||
function M:_add(keys)
|
function M:_add(keys)
|
||||||
local lhs = keys.lhs
|
local lhs = keys.lhs
|
||||||
|
@ -114,10 +109,6 @@ function M:_add(keys)
|
||||||
|
|
||||||
---@param buf? number
|
---@param buf? number
|
||||||
local function add(buf)
|
local function add(buf)
|
||||||
if M.is_nop(keys) then
|
|
||||||
return self:_set(keys, buf)
|
|
||||||
end
|
|
||||||
|
|
||||||
vim.keymap.set(keys.mode, lhs, function()
|
vim.keymap.set(keys.mode, lhs, function()
|
||||||
local plugins = self.active[keys.id]
|
local plugins = self.active[keys.id]
|
||||||
|
|
||||||
|
@ -152,7 +143,7 @@ function M:_add(keys)
|
||||||
vim.api.nvim_create_autocmd("FileType", {
|
vim.api.nvim_create_autocmd("FileType", {
|
||||||
pattern = keys.ft,
|
pattern = keys.ft,
|
||||||
callback = function(event)
|
callback = function(event)
|
||||||
if self.active[keys.id] and not M.is_nop(keys) then
|
if self.active[keys.id] then
|
||||||
add(event.buf)
|
add(event.buf)
|
||||||
else
|
else
|
||||||
-- Only create the mapping if its managed by lazy
|
-- Only create the mapping if its managed by lazy
|
||||||
|
|
|
@ -44,7 +44,6 @@ function M.setup()
|
||||||
while M.install_missing() do
|
while M.install_missing() do
|
||||||
count = count + 1
|
count = count + 1
|
||||||
if count > 5 then
|
if count > 5 then
|
||||||
Util.error("Too many rounds of missing plugins")
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -67,10 +66,7 @@ end
|
||||||
-- multiple rounds can happen when importing a spec from a missing plugin
|
-- multiple rounds can happen when importing a spec from a missing plugin
|
||||||
function M.install_missing()
|
function M.install_missing()
|
||||||
for _, plugin in pairs(Config.plugins) do
|
for _, plugin in pairs(Config.plugins) do
|
||||||
local installed = plugin._.installed
|
if not (plugin._.installed or Plugin.has_errors(plugin)) then
|
||||||
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
|
for _, colorscheme in ipairs(Config.options.install.colorscheme) do
|
||||||
if colorscheme == "default" then
|
if colorscheme == "default" then
|
||||||
break
|
break
|
||||||
|
@ -104,7 +100,7 @@ function M.startup()
|
||||||
M.source(vim.env.VIMRUNTIME .. "/filetype.lua")
|
M.source(vim.env.VIMRUNTIME .. "/filetype.lua")
|
||||||
|
|
||||||
-- backup original rtp
|
-- backup original rtp
|
||||||
local rtp = vim.opt.rtp:get() --[[@as string[] ]]
|
local rtp = vim.opt.rtp:get()
|
||||||
|
|
||||||
-- 1. run plugin init
|
-- 1. run plugin init
|
||||||
Util.track({ start = "init" })
|
Util.track({ start = "init" })
|
||||||
|
@ -135,7 +131,7 @@ function M.startup()
|
||||||
if not path:find("after/?$") then
|
if not path:find("after/?$") then
|
||||||
-- these paths don't will already have their ftdetect ran,
|
-- these paths don't will already have their ftdetect ran,
|
||||||
-- by sourcing filetype.lua above, so skip them
|
-- by sourcing filetype.lua above, so skip them
|
||||||
M.did_ftdetect[path] = path
|
M.did_ftdetect[path] = true
|
||||||
M.packadd(path)
|
M.packadd(path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -143,9 +139,7 @@ function M.startup()
|
||||||
|
|
||||||
-- 4. load after plugins
|
-- 4. load after plugins
|
||||||
Util.track({ start = "after" })
|
Util.track({ start = "after" })
|
||||||
for _, path in
|
for _, path in ipairs(vim.opt.rtp:get()) do
|
||||||
ipairs(vim.opt.rtp:get() --[[@as string[] ]])
|
|
||||||
do
|
|
||||||
if path:find("after/?$") then
|
if path:find("after/?$") then
|
||||||
M.source_runtime(path, "plugin")
|
M.source_runtime(path, "plugin")
|
||||||
end
|
end
|
||||||
|
@ -161,7 +155,7 @@ function M.get_start_plugins()
|
||||||
---@type LazyPlugin[]
|
---@type LazyPlugin[]
|
||||||
local start = {}
|
local start = {}
|
||||||
for _, plugin in pairs(Config.plugins) do
|
for _, plugin in pairs(Config.plugins) do
|
||||||
if not plugin._.loaded and (plugin._.rtp_loaded or plugin.lazy == false) then
|
if plugin.lazy == false and not plugin._.loaded then
|
||||||
start[#start + 1] = plugin
|
start[#start + 1] = plugin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -341,13 +335,7 @@ function M._load(plugin, reason, opts)
|
||||||
Util.track({ plugin = plugin.name, start = reason.start })
|
Util.track({ plugin = plugin.name, start = reason.start })
|
||||||
Handler.disable(plugin)
|
Handler.disable(plugin)
|
||||||
|
|
||||||
if not plugin.virtual then
|
|
||||||
M.add_to_rtp(plugin)
|
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
|
if plugin.dependencies then
|
||||||
Util.try(function()
|
Util.try(function()
|
||||||
|
@ -355,9 +343,7 @@ function M._load(plugin, reason, opts)
|
||||||
end, "Failed to load deps for " .. plugin.name)
|
end, "Failed to load deps for " .. plugin.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not plugin.virtual then
|
|
||||||
M.packadd(plugin.dir)
|
M.packadd(plugin.dir)
|
||||||
end
|
|
||||||
if plugin.config or plugin.opts then
|
if plugin.config or plugin.opts then
|
||||||
M.config(plugin)
|
M.config(plugin)
|
||||||
end
|
end
|
||||||
|
@ -468,8 +454,10 @@ function M.add_to_rtp(plugin)
|
||||||
local rtp = vim.api.nvim_get_runtime_file("", true)
|
local rtp = vim.api.nvim_get_runtime_file("", true)
|
||||||
local idx_dir, idx_after
|
local idx_dir, idx_after
|
||||||
|
|
||||||
|
local is_win = jit.os:find("Windows")
|
||||||
|
|
||||||
for i, path in ipairs(rtp) do
|
for i, path in ipairs(rtp) do
|
||||||
if Util.is_win then
|
if is_win then
|
||||||
path = Util.norm(path)
|
path = Util.norm(path)
|
||||||
end
|
end
|
||||||
if path == Config.me then
|
if path == Config.me then
|
||||||
|
@ -488,22 +476,9 @@ function M.add_to_rtp(plugin)
|
||||||
table.insert(rtp, idx_after or (#rtp + 1), after)
|
table.insert(rtp, idx_after or (#rtp + 1), after)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type vim.Option
|
|
||||||
vim.opt.rtp = rtp
|
vim.opt.rtp = rtp
|
||||||
end
|
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)
|
function M.source(path)
|
||||||
Util.track({ runtime = path })
|
Util.track({ runtime = path })
|
||||||
Util.try(function()
|
Util.try(function()
|
||||||
|
@ -529,8 +504,8 @@ function M.colorscheme(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.auto_load(modname, modpath)
|
function M.auto_load(modname, modpath)
|
||||||
local plugin = Plugin.find(modpath, { fast = not M.did_handlers })
|
local plugin = Plugin.find(modpath)
|
||||||
if plugin then
|
if plugin and modpath:find(plugin.dir, 1, true) == 1 then
|
||||||
plugin._.rtp_loaded = true
|
plugin._.rtp_loaded = true
|
||||||
-- don't load if:
|
-- don't load if:
|
||||||
-- * handlers haven't been setup yet
|
-- * handlers haven't been setup yet
|
||||||
|
@ -550,17 +525,9 @@ end
|
||||||
|
|
||||||
---@param modname string
|
---@param modname string
|
||||||
function M.loader(modname)
|
function M.loader(modname)
|
||||||
local paths, cached = Util.get_unloaded_rtp(modname, { cache = true })
|
local paths = Util.get_unloaded_rtp(modname)
|
||||||
local ret = Cache.find(modname, { rtp = false, paths = paths })[1]
|
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
|
if ret then
|
||||||
-- explicitly set to nil to prevent loading errors
|
|
||||||
package.loaded[modname] = nil
|
|
||||||
M.auto_load(modname, ret.modpath)
|
M.auto_load(modname, ret.modpath)
|
||||||
local mod = package.loaded[modname]
|
local mod = package.loaded[modname]
|
||||||
if type(mod) == "table" then
|
if type(mod) == "table" then
|
||||||
|
|
|
@ -1,360 +0,0 @@
|
||||||
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
|
|
|
@ -1,6 +1,4 @@
|
||||||
local Config = require("lazy.core.config")
|
local Config = require("lazy.core.config")
|
||||||
local Meta = require("lazy.core.meta")
|
|
||||||
local Pkg = require("lazy.pkg")
|
|
||||||
local Util = require("lazy.core.util")
|
local Util = require("lazy.core.util")
|
||||||
|
|
||||||
---@class LazyCorePlugin
|
---@class LazyCorePlugin
|
||||||
|
@ -8,9 +6,10 @@ local M = {}
|
||||||
M.loading = false
|
M.loading = false
|
||||||
|
|
||||||
---@class LazySpecLoader
|
---@class LazySpecLoader
|
||||||
---@field meta LazyMeta
|
|
||||||
---@field plugins table<string, LazyPlugin>
|
---@field plugins table<string, LazyPlugin>
|
||||||
|
---@field fragments table<number, LazyPlugin>
|
||||||
---@field disabled table<string, LazyPlugin>
|
---@field disabled table<string, LazyPlugin>
|
||||||
|
---@field dirty table<string, true>
|
||||||
---@field ignore_installed table<string, true>
|
---@field ignore_installed table<string, true>
|
||||||
---@field modules string[]
|
---@field modules string[]
|
||||||
---@field notifs {msg:string, level:number, file?:string}[]
|
---@field notifs {msg:string, level:number, file?:string}[]
|
||||||
|
@ -18,44 +17,34 @@ M.loading = false
|
||||||
---@field optional? boolean
|
---@field optional? boolean
|
||||||
local Spec = {}
|
local Spec = {}
|
||||||
M.Spec = Spec
|
M.Spec = Spec
|
||||||
|
M.last_fid = 0
|
||||||
|
M.fid_stack = {} ---@type number[]
|
||||||
M.LOCAL_SPEC = ".lazy.lua"
|
M.LOCAL_SPEC = ".lazy.lua"
|
||||||
|
|
||||||
---@param spec? LazySpec
|
---@param spec? LazySpec
|
||||||
---@param opts? {optional?:boolean, pkg?:boolean}
|
---@param opts? {optional?:boolean}
|
||||||
function Spec.new(spec, opts)
|
function Spec.new(spec, opts)
|
||||||
local self = setmetatable({}, Spec)
|
local self = setmetatable({}, { __index = Spec })
|
||||||
self.meta = Meta.new(self)
|
self.plugins = {}
|
||||||
|
self.fragments = {}
|
||||||
self.disabled = {}
|
self.disabled = {}
|
||||||
self.modules = {}
|
self.modules = {}
|
||||||
|
self.dirty = {}
|
||||||
self.notifs = {}
|
self.notifs = {}
|
||||||
self.ignore_installed = {}
|
self.ignore_installed = {}
|
||||||
self.optional = opts and opts.optional
|
self.optional = opts and opts.optional
|
||||||
if not (opts and opts.pkg == false) then
|
|
||||||
self.meta:load_pkgs()
|
|
||||||
end
|
|
||||||
if spec then
|
if spec then
|
||||||
self:parse(spec)
|
self:parse(spec)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function Spec:__index(key)
|
|
||||||
if Spec[key] then
|
|
||||||
return Spec[key]
|
|
||||||
end
|
|
||||||
if key == "plugins" then
|
|
||||||
self.meta:rebuild()
|
|
||||||
return self.meta.plugins
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Spec:parse(spec)
|
function Spec:parse(spec)
|
||||||
self:normalize(spec)
|
self:normalize(spec)
|
||||||
self.meta:resolve()
|
self:fix_disabled()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- PERF: optimized code to get package name without using lua patterns
|
-- PERF: optimized code to get package name without using lua patterns
|
||||||
---@return string
|
|
||||||
function Spec.get_name(pkg)
|
function Spec.get_name(pkg)
|
||||||
local name = pkg:sub(-4) == ".git" and pkg:sub(1, -5) or 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
|
name = name:sub(-1) == "/" and name:sub(1, -2) or name
|
||||||
|
@ -63,6 +52,120 @@ function Spec.get_name(pkg)
|
||||||
return slash and name:sub(#name - slash + 2) or pkg:gsub("%W+", "_")
|
return slash and name:sub(#name - slash + 2) or pkg:gsub("%W+", "_")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param plugin LazyPlugin
|
||||||
|
---@param results? string[]
|
||||||
|
function Spec:add(plugin, results)
|
||||||
|
-- check if we already processed this spec. Can happen when a user uses the same instance of a spec in multiple specs
|
||||||
|
-- see https://github.com/folke/lazy.nvim/issues/45
|
||||||
|
if rawget(plugin, "_") then
|
||||||
|
if results then
|
||||||
|
table.insert(results, plugin.name)
|
||||||
|
end
|
||||||
|
return plugin
|
||||||
|
end
|
||||||
|
|
||||||
|
local is_ref = plugin[1] and not plugin[1]:find("/", 1, true)
|
||||||
|
|
||||||
|
if not plugin.url and not is_ref and plugin[1] then
|
||||||
|
local prefix = plugin[1]:sub(1, 4)
|
||||||
|
if prefix == "http" or prefix == "git@" then
|
||||||
|
plugin.url = plugin[1]
|
||||||
|
else
|
||||||
|
plugin.url = Config.options.git.url_format:format(plugin[1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@type string?
|
||||||
|
local dir
|
||||||
|
|
||||||
|
if plugin.dir then
|
||||||
|
dir = Util.norm(plugin.dir)
|
||||||
|
-- local plugin
|
||||||
|
plugin.name = plugin.name or Spec.get_name(plugin.dir)
|
||||||
|
elseif plugin.url then
|
||||||
|
plugin.name = plugin.name or Spec.get_name(plugin.url)
|
||||||
|
-- check for dev plugins
|
||||||
|
if plugin.dev == nil 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
|
||||||
|
elseif is_ref then
|
||||||
|
plugin.name = plugin[1]
|
||||||
|
else
|
||||||
|
self:error("Invalid plugin spec " .. vim.inspect(plugin))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if not plugin.name or plugin.name == "" then
|
||||||
|
self:error("Plugin spec " .. vim.inspect(plugin) .. " has no name")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- dev plugins
|
||||||
|
if plugin.dev then
|
||||||
|
local dir_dev
|
||||||
|
if type(Config.options.dev.path) == "string" then
|
||||||
|
dir_dev = Config.options.dev.path .. "/" .. plugin.name
|
||||||
|
else
|
||||||
|
dir_dev = Util.norm(Config.options.dev.path(plugin))
|
||||||
|
end
|
||||||
|
if not Config.options.dev.fallback or vim.fn.isdirectory(dir_dev) == 1 then
|
||||||
|
dir = dir_dev
|
||||||
|
end
|
||||||
|
elseif plugin.dev == false then
|
||||||
|
-- explicitely select the default path
|
||||||
|
dir = Config.options.root .. "/" .. plugin.name
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(plugin.config) == "table" then
|
||||||
|
self:warn(
|
||||||
|
"{" .. plugin.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
|
||||||
|
|
||||||
|
local fpid = M.fid_stack[#M.fid_stack]
|
||||||
|
|
||||||
|
M.last_fid = M.last_fid + 1
|
||||||
|
plugin._ = {
|
||||||
|
dir = dir,
|
||||||
|
fid = M.last_fid,
|
||||||
|
fpid = fpid,
|
||||||
|
dep = fpid ~= nil,
|
||||||
|
module = self.importing,
|
||||||
|
}
|
||||||
|
self.fragments[plugin._.fid] = plugin
|
||||||
|
-- remote plugin
|
||||||
|
plugin.dir = plugin._.dir or (plugin.name and (Config.options.root .. "/" .. plugin.name)) or nil
|
||||||
|
|
||||||
|
if fpid then
|
||||||
|
local parent = self.fragments[fpid]
|
||||||
|
parent._.fdeps = parent._.fdeps or {}
|
||||||
|
table.insert(parent._.fdeps, plugin._.fid)
|
||||||
|
end
|
||||||
|
|
||||||
|
if plugin.dependencies then
|
||||||
|
table.insert(M.fid_stack, plugin._.fid)
|
||||||
|
plugin.dependencies = self:normalize(plugin.dependencies, {})
|
||||||
|
table.remove(M.fid_stack)
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.plugins[plugin.name] then
|
||||||
|
plugin = self:merge(self.plugins[plugin.name], plugin)
|
||||||
|
end
|
||||||
|
self.plugins[plugin.name] = plugin
|
||||||
|
if results then
|
||||||
|
table.insert(results, plugin.name)
|
||||||
|
end
|
||||||
|
return plugin
|
||||||
|
end
|
||||||
|
|
||||||
function Spec:error(msg)
|
function Spec:error(msg)
|
||||||
self:log(msg, vim.log.levels.ERROR)
|
self:log(msg, vim.log.levels.ERROR)
|
||||||
end
|
end
|
||||||
|
@ -71,6 +174,155 @@ function Spec:warn(msg)
|
||||||
self:log(msg, vim.log.levels.WARN)
|
self:log(msg, vim.log.levels.WARN)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Rebuilds a plugin spec excluding any removed fragments
|
||||||
|
---@param name? string
|
||||||
|
function Spec:rebuild(name)
|
||||||
|
if not name then
|
||||||
|
for n, _ in pairs(self.dirty) do
|
||||||
|
self:rebuild(n)
|
||||||
|
end
|
||||||
|
self.dirty = {}
|
||||||
|
end
|
||||||
|
local plugin = self.plugins[name]
|
||||||
|
if not plugin then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local fragments = {} ---@type LazyPlugin[]
|
||||||
|
|
||||||
|
repeat
|
||||||
|
local super = plugin._.super
|
||||||
|
if self.fragments[plugin._.fid] then
|
||||||
|
plugin._.dep = plugin._.fpid ~= nil
|
||||||
|
plugin._.super = nil
|
||||||
|
if plugin._.fdeps then
|
||||||
|
plugin.dependencies = {}
|
||||||
|
for _, cid in ipairs(plugin._.fdeps) do
|
||||||
|
if self.fragments[cid] then
|
||||||
|
table.insert(plugin.dependencies, self.fragments[cid].name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
setmetatable(plugin, nil)
|
||||||
|
table.insert(fragments, 1, plugin)
|
||||||
|
end
|
||||||
|
plugin = super
|
||||||
|
until not plugin
|
||||||
|
|
||||||
|
if #fragments == 0 then
|
||||||
|
self.plugins[name] = nil
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
plugin = fragments[1]
|
||||||
|
for i = 2, #fragments do
|
||||||
|
plugin = self:merge(plugin, fragments[i])
|
||||||
|
end
|
||||||
|
self.plugins[name] = plugin
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Recursively removes all fragments from a plugin spec or a given fragment
|
||||||
|
---@param id string|number Plugin name or fragment id
|
||||||
|
---@param opts {self: boolean}
|
||||||
|
function Spec:remove_fragments(id, opts)
|
||||||
|
local fids = {} ---@type number[]
|
||||||
|
|
||||||
|
if type(id) == "number" then
|
||||||
|
fids[1] = id
|
||||||
|
else
|
||||||
|
local plugin = self.plugins[id]
|
||||||
|
repeat
|
||||||
|
fids[#fids + 1] = plugin._.fid
|
||||||
|
plugin = plugin._.super
|
||||||
|
until not plugin
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, fid in ipairs(fids) do
|
||||||
|
local fragment = self.fragments[fid]
|
||||||
|
if fragment then
|
||||||
|
for _, cid in ipairs(fragment._.fdeps or {}) do
|
||||||
|
self:remove_fragments(cid, { self = true })
|
||||||
|
end
|
||||||
|
if opts.self then
|
||||||
|
self.fragments[fid] = nil
|
||||||
|
end
|
||||||
|
self.dirty[fragment.name] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Spec: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)
|
||||||
|
if not self.ignore_installed[p.name] then
|
||||||
|
for _, dep in ipairs(p.dependencies or {}) do
|
||||||
|
table.insert(stack, self.plugins[dep])
|
||||||
|
end
|
||||||
|
self.ignore_installed[p.name] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
plugin.enabled = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Spec:fix_optional()
|
||||||
|
if not self.optional then
|
||||||
|
---@param plugin LazyPlugin
|
||||||
|
local function all_optional(plugin)
|
||||||
|
return (not plugin) or (rawget(plugin, "optional") and all_optional(plugin._.super))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- handle optional plugins
|
||||||
|
for _, plugin in pairs(self.plugins) do
|
||||||
|
if plugin.optional and all_optional(plugin) then
|
||||||
|
-- remove all optional fragments
|
||||||
|
self:remove_fragments(plugin.name, { self = true })
|
||||||
|
self.plugins[plugin.name] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Spec:fix_disabled()
|
||||||
|
for _, plugin in pairs(self.plugins) do
|
||||||
|
if not plugin.name or not plugin.dir then
|
||||||
|
self:error("Plugin spec for **" .. plugin.name .. "** not found.\n```lua\n" .. vim.inspect(plugin) .. "\n```")
|
||||||
|
self.plugins[plugin.name] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self:fix_optional()
|
||||||
|
self:rebuild()
|
||||||
|
|
||||||
|
self:fix_cond()
|
||||||
|
self:rebuild()
|
||||||
|
|
||||||
|
self.dirty = {}
|
||||||
|
|
||||||
|
for _, plugin in pairs(self.plugins) do
|
||||||
|
local disabled = plugin.enabled == false or (type(plugin.enabled) == "function" and not plugin.enabled())
|
||||||
|
if disabled then
|
||||||
|
plugin._.kind = "disabled"
|
||||||
|
-- remove all child fragments
|
||||||
|
self:remove_fragments(plugin.name, { self = false })
|
||||||
|
self.plugins[plugin.name] = nil
|
||||||
|
self.disabled[plugin.name] = plugin
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- rebuild any plugin specs that were modified
|
||||||
|
self:rebuild()
|
||||||
|
end
|
||||||
|
|
||||||
---@param msg string
|
---@param msg string
|
||||||
---@param level number
|
---@param level number
|
||||||
function Spec:log(msg, level)
|
function Spec:log(msg, level)
|
||||||
|
@ -90,21 +342,29 @@ function Spec:report(level)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param spec LazySpec|LazySpecImport
|
---@param spec LazySpec|LazySpecImport
|
||||||
function Spec:normalize(spec)
|
---@param results? string[]
|
||||||
|
function Spec:normalize(spec, results)
|
||||||
if type(spec) == "string" then
|
if type(spec) == "string" then
|
||||||
self.meta:add({ spec })
|
if not spec:find("/", 1, true) then
|
||||||
|
-- spec is a plugin name
|
||||||
|
if results then
|
||||||
|
table.insert(results, spec)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:add({ spec }, results)
|
||||||
|
end
|
||||||
elseif #spec > 1 or Util.is_list(spec) then
|
elseif #spec > 1 or Util.is_list(spec) then
|
||||||
---@cast spec LazySpec[]
|
---@cast spec LazySpec[]
|
||||||
for _, s in ipairs(spec) do
|
for _, s in ipairs(spec) do
|
||||||
self:normalize(s)
|
self:normalize(s, results)
|
||||||
end
|
end
|
||||||
elseif spec[1] or spec.dir or spec.url then
|
elseif spec[1] or spec.dir or spec.url then
|
||||||
---@cast spec LazyPluginSpec
|
---@cast spec LazyPlugin
|
||||||
self.meta:add(spec)
|
local plugin = self:add(spec, results)
|
||||||
---@diagnostic disable-next-line: cast-type-mismatch
|
---@diagnostic disable-next-line: cast-type-mismatch
|
||||||
---@cast spec LazySpecImport
|
---@cast plugin LazySpecImport
|
||||||
if spec and spec.import then
|
if plugin and plugin.import then
|
||||||
self:import(spec)
|
self:import(plugin)
|
||||||
end
|
end
|
||||||
elseif spec.import then
|
elseif spec.import then
|
||||||
---@cast spec LazySpecImport
|
---@cast spec LazySpecImport
|
||||||
|
@ -112,6 +372,7 @@ function Spec:normalize(spec)
|
||||||
else
|
else
|
||||||
self:error("Invalid plugin spec " .. vim.inspect(spec))
|
self:error("Invalid plugin spec " .. vim.inspect(spec))
|
||||||
end
|
end
|
||||||
|
return results
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param spec LazySpecImport
|
---@param spec LazySpecImport
|
||||||
|
@ -119,18 +380,10 @@ function Spec:import(spec)
|
||||||
if spec.import == "lazy" then
|
if spec.import == "lazy" then
|
||||||
return self:error("You can't name your plugins module `lazy`.")
|
return self:error("You can't name your plugins module `lazy`.")
|
||||||
end
|
end
|
||||||
if type(spec.import) == "function" then
|
if type(spec.import) ~= "string" 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))
|
return self:error("Invalid import spec. `import` should be a string: " .. vim.inspect(spec))
|
||||||
end
|
end
|
||||||
|
if vim.tbl_contains(self.modules, spec.import) then
|
||||||
local import_name = spec.name or spec.import
|
|
||||||
---@cast import_name string
|
|
||||||
|
|
||||||
if vim.tbl_contains(self.modules, import_name) then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if spec.cond == false or (type(spec.cond) == "function" and not spec.cond()) then
|
if spec.cond == false or (type(spec.cond) == "function" and not spec.cond()) then
|
||||||
|
@ -140,49 +393,38 @@ function Spec:import(spec)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
self.modules[#self.modules + 1] = import_name
|
self.modules[#self.modules + 1] = spec.import
|
||||||
|
|
||||||
local import = spec.import
|
|
||||||
|
|
||||||
local imported = 0
|
local imported = 0
|
||||||
|
|
||||||
---@type {modname: string, load: fun():(LazyPluginSpec?, string?)}[]
|
---@type string[]
|
||||||
local modspecs = {}
|
local modnames = {}
|
||||||
|
|
||||||
if type(import) == "string" then
|
if spec.import == M.LOCAL_SPEC then
|
||||||
Util.lsmod(import, function(modname, modpath)
|
modnames = { spec.import }
|
||||||
modspecs[#modspecs + 1] = {
|
|
||||||
modname = modname,
|
|
||||||
load = function()
|
|
||||||
local mod, err = loadfile(modpath)
|
|
||||||
if mod then
|
|
||||||
return mod()
|
|
||||||
else
|
else
|
||||||
return nil, err
|
Util.lsmod(spec.import, function(modname)
|
||||||
end
|
modnames[#modnames + 1] = modname
|
||||||
end,
|
|
||||||
}
|
|
||||||
end)
|
end)
|
||||||
table.sort(modspecs, function(a, b)
|
table.sort(modnames)
|
||||||
return a.modname < b.modname
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
modspecs = { { modname = import_name, load = spec.import } }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, modspec in ipairs(modspecs) do
|
for _, modname in ipairs(modnames) do
|
||||||
imported = imported + 1
|
imported = imported + 1
|
||||||
local modname = modspec.modname
|
|
||||||
Util.track({ import = modname })
|
Util.track({ import = modname })
|
||||||
self.importing = modname
|
self.importing = modname
|
||||||
-- unload the module so we get a clean slate
|
-- unload the module so we get a clean slate
|
||||||
---@diagnostic disable-next-line: no-unknown
|
---@diagnostic disable-next-line: no-unknown
|
||||||
package.loaded[modname] = nil
|
package.loaded[modname] = nil
|
||||||
Util.try(function()
|
Util.try(function()
|
||||||
local mod, err = modspec.load()
|
local mod = nil
|
||||||
if err then
|
if modname == M.LOCAL_SPEC then
|
||||||
self:error("Failed to load `" .. modname .. "`:\n" .. err)
|
mod = M.local_spec()
|
||||||
elseif type(mod) ~= "table" then
|
else
|
||||||
|
mod = require(modname)
|
||||||
|
end
|
||||||
|
if type(mod) ~= "table" then
|
||||||
|
self.importing = nil
|
||||||
return self:error(
|
return self:error(
|
||||||
"Invalid spec module: `"
|
"Invalid spec module: `"
|
||||||
.. modname
|
.. modname
|
||||||
|
@ -190,23 +432,59 @@ function Spec:import(spec)
|
||||||
.. type(mod)
|
.. type(mod)
|
||||||
.. "` was returned instead"
|
.. "` was returned instead"
|
||||||
)
|
)
|
||||||
else
|
|
||||||
self:normalize(mod)
|
|
||||||
end
|
end
|
||||||
|
self:normalize(mod)
|
||||||
|
self.importing = nil
|
||||||
|
Util.track()
|
||||||
end, {
|
end, {
|
||||||
msg = "Failed to load `" .. modname .. "`",
|
msg = "Failed to load `" .. modname .. "`",
|
||||||
on_error = function(msg)
|
on_error = function(msg)
|
||||||
self:error(msg)
|
self:error(msg)
|
||||||
end,
|
|
||||||
})
|
|
||||||
self.importing = nil
|
self.importing = nil
|
||||||
Util.track()
|
Util.track()
|
||||||
|
end,
|
||||||
|
})
|
||||||
end
|
end
|
||||||
if imported == 0 then
|
if imported == 0 then
|
||||||
self:error("No specs found for module " .. vim.inspect(spec.import))
|
self:error("No specs found for module " .. spec.import)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param old LazyPlugin
|
||||||
|
---@param new LazyPlugin
|
||||||
|
---@return LazyPlugin
|
||||||
|
function Spec:merge(old, new)
|
||||||
|
new._.dep = old._.dep and new._.dep
|
||||||
|
|
||||||
|
if new.url and old.url and new.url ~= old.url then
|
||||||
|
self:warn("Two plugins with the same name and different url:\n" .. vim.inspect({ old = old, new = new }))
|
||||||
|
end
|
||||||
|
|
||||||
|
if new.dependencies and old.dependencies then
|
||||||
|
Util.extend(new.dependencies, old.dependencies)
|
||||||
|
end
|
||||||
|
|
||||||
|
local new_dir = new._.dir or old._.dir or (new.name and (Config.options.root .. "/" .. new.name)) or nil
|
||||||
|
if new_dir ~= old.dir then
|
||||||
|
local msg = "Plugin `" .. new.name .. "` changed `dir`:\n- from: `" .. old.dir .. "`\n- to: `" .. new_dir .. "`"
|
||||||
|
if new._.rtp_loaded or old._.rtp_loaded then
|
||||||
|
msg = msg
|
||||||
|
.. "\n\nThis plugin was already partially loaded, so we did not change it's `dir`.\nPlease fix your config."
|
||||||
|
self:error(msg)
|
||||||
|
new_dir = old.dir
|
||||||
|
else
|
||||||
|
self:warn(msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
new.dir = new_dir
|
||||||
|
new._.rtp_loaded = new._.rtp_loaded or old._.rtp_loaded
|
||||||
|
|
||||||
|
new._.super = old
|
||||||
|
setmetatable(new, { __index = old })
|
||||||
|
|
||||||
|
return new
|
||||||
|
end
|
||||||
|
|
||||||
function M.update_state()
|
function M.update_state()
|
||||||
---@type string[]
|
---@type string[]
|
||||||
local cloning = {}
|
local cloning = {}
|
||||||
|
@ -237,15 +515,12 @@ function M.update_state()
|
||||||
or plugin.cmd
|
or plugin.cmd
|
||||||
plugin.lazy = lazy and true or false
|
plugin.lazy = lazy and true or false
|
||||||
end
|
end
|
||||||
if plugin.virtual then
|
if plugin.dir:find(Config.options.root, 1, true) == 1 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
|
plugin._.installed = installed[plugin.name] ~= nil
|
||||||
installed[plugin.name] = nil
|
installed[plugin.name] = nil
|
||||||
else
|
else
|
||||||
plugin._.is_local = true
|
plugin._.is_local = true
|
||||||
plugin._.installed = vim.fn.isdirectory(plugin.dir) == 1
|
plugin._.installed = true -- local plugins are managed by the user
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -253,8 +528,6 @@ function M.update_state()
|
||||||
installed[name] = nil
|
installed[name] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
M.update_rocks_state()
|
|
||||||
|
|
||||||
Config.to_clean = {}
|
Config.to_clean = {}
|
||||||
for pack, dir_type in pairs(installed) do
|
for pack, dir_type in pairs(installed) do
|
||||||
table.insert(Config.to_clean, {
|
table.insert(Config.to_clean, {
|
||||||
|
@ -270,49 +543,13 @@ function M.update_state()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.update_rocks_state()
|
function M.local_spec()
|
||||||
local root = Config.options.rocks.root
|
local filepath = vim.fn.fnamemodify(".lazy.lua", ":p")
|
||||||
---@type table<string,string>
|
local file = vim.secure.read(filepath)
|
||||||
local installed = {}
|
if file then
|
||||||
Util.ls(root, function(_, name, type)
|
return loadstring(file)()
|
||||||
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
|
|
||||||
|
|
||||||
---@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
|
end
|
||||||
return {}
|
return {}
|
||||||
end,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
local p = vim.fn.fnamemodify(path, ":h")
|
|
||||||
if p == path then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
path = p
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.load()
|
function M.load()
|
||||||
|
@ -320,15 +557,16 @@ function M.load()
|
||||||
-- load specs
|
-- load specs
|
||||||
Util.track("spec")
|
Util.track("spec")
|
||||||
Config.spec = Spec.new()
|
Config.spec = Spec.new()
|
||||||
|
Config.spec:parse({
|
||||||
local specs = {
|
|
||||||
---@diagnostic disable-next-line: param-type-mismatch
|
|
||||||
vim.deepcopy(Config.options.spec),
|
vim.deepcopy(Config.options.spec),
|
||||||
}
|
{
|
||||||
specs[#specs + 1] = M.find_local_spec()
|
import = ".lazy.lua",
|
||||||
specs[#specs + 1] = { "folke/lazy.nvim" }
|
cond = function()
|
||||||
|
return Config.options.local_spec and vim.fn.filereadable(M.LOCAL_SPEC) == 1
|
||||||
Config.spec:parse(specs)
|
end,
|
||||||
|
},
|
||||||
|
{ "folke/lazy.nvim" },
|
||||||
|
})
|
||||||
|
|
||||||
-- override some lazy props
|
-- override some lazy props
|
||||||
local lazy = Config.spec.plugins["lazy.nvim"]
|
local lazy = Config.spec.plugins["lazy.nvim"]
|
||||||
|
@ -341,30 +579,16 @@ function M.load()
|
||||||
lazy._.loaded = {}
|
lazy._.loaded = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 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
|
local existing = Config.plugins
|
||||||
Config.plugins = Config.spec.plugins
|
Config.plugins = Config.spec.plugins
|
||||||
-- copy state. This wont do anything during startup
|
-- copy state. This wont do anything during startup
|
||||||
for name, plugin in pairs(existing) do
|
for name, plugin in pairs(existing) do
|
||||||
if Config.plugins[name] then
|
if Config.plugins[name] then
|
||||||
local new_state = Config.plugins[name]._
|
local dep = Config.plugins[name]._.dep
|
||||||
|
local super = Config.plugins[name]._.super
|
||||||
Config.plugins[name]._ = plugin._
|
Config.plugins[name]._ = plugin._
|
||||||
Config.plugins[name]._.dep = new_state.dep
|
Config.plugins[name]._.dep = dep
|
||||||
Config.plugins[name]._.frags = new_state.frags
|
Config.plugins[name]._.super = super
|
||||||
Config.plugins[name]._.pkg = new_state.pkg
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Util.track()
|
Util.track()
|
||||||
|
@ -372,36 +596,23 @@ function M.load()
|
||||||
Util.track("state")
|
Util.track("state")
|
||||||
M.update_state()
|
M.update_state()
|
||||||
Util.track()
|
Util.track()
|
||||||
|
|
||||||
if Config.options.pkg.enabled and Pkg.dirty then
|
|
||||||
Pkg.update()
|
|
||||||
return M.load()
|
|
||||||
end
|
|
||||||
|
|
||||||
M.loading = false
|
M.loading = false
|
||||||
vim.api.nvim_exec_autocmds("User", { pattern = "LazyPlugins", modeline = false })
|
vim.api.nvim_exec_autocmds("User", { pattern = "LazyPlugins", modeline = false })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Finds the plugin that has this path
|
-- Finds the plugin that has this path
|
||||||
---@param path string
|
---@param path string
|
||||||
---@param opts? {fast?:boolean}
|
function M.find(path)
|
||||||
function M.find(path, opts)
|
|
||||||
if not Config.spec then
|
if not Config.spec then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
opts = opts or {}
|
|
||||||
local lua = path:find("/lua/", 1, true)
|
local lua = path:find("/lua/", 1, true)
|
||||||
if lua then
|
if lua then
|
||||||
local name = path:sub(1, lua - 1)
|
local name = path:sub(1, lua - 1)
|
||||||
local slash = name:reverse():find("/", 1, true)
|
local slash = name:reverse():find("/", 1, true)
|
||||||
if slash then
|
if slash then
|
||||||
name = name:sub(#name - slash + 2)
|
name = name:sub(#name - slash + 2)
|
||||||
if name then
|
return name and Config.plugins[name] or Config.spec.plugins[name] or nil
|
||||||
if opts.fast then
|
|
||||||
return Config.spec.meta.plugins[name]
|
|
||||||
end
|
|
||||||
return Config.spec.plugins[name]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -409,7 +620,7 @@ end
|
||||||
---@param plugin LazyPlugin
|
---@param plugin LazyPlugin
|
||||||
function M.has_errors(plugin)
|
function M.has_errors(plugin)
|
||||||
for _, task in ipairs(plugin._.tasks or {}) do
|
for _, task in ipairs(plugin._.tasks or {}) do
|
||||||
if task:has_errors() then
|
if task.error then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -444,9 +655,8 @@ function M._values(root, plugin, prop, is_list)
|
||||||
if not plugin[prop] then
|
if not plugin[prop] then
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
local super = getmetatable(plugin)
|
|
||||||
---@type table
|
---@type table
|
||||||
local ret = super and M._values(root, super.__index, prop, is_list) or {}
|
local ret = plugin._.super and M._values(root, plugin._.super, prop, is_list) or {}
|
||||||
local values = rawget(plugin, prop)
|
local values = rawget(plugin, prop)
|
||||||
|
|
||||||
if not values then
|
if not values then
|
||||||
|
@ -457,28 +667,7 @@ function M._values(root, plugin, prop, is_list)
|
||||||
end
|
end
|
||||||
|
|
||||||
values = type(values) == "table" and values or { values }
|
values = type(values) == "table" and values or { values }
|
||||||
if is_list then
|
return is_list and Util.extend(ret, values) or Util.merge(ret, values)
|
||||||
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
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|
|
@ -5,7 +5,6 @@ local M = {}
|
||||||
|
|
||||||
---@type LazyProfile[]
|
---@type LazyProfile[]
|
||||||
M._profiles = { { name = "lazy" } }
|
M._profiles = { { name = "lazy" } }
|
||||||
M.is_win = jit.os:find("Windows")
|
|
||||||
|
|
||||||
---@param data (string|{[string]:string})?
|
---@param data (string|{[string]:string})?
|
||||||
---@param time number?
|
---@param time number?
|
||||||
|
@ -29,24 +28,6 @@ function M.track(data, time)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
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()
|
---@generic F: fun()
|
||||||
---@param data (string|{[string]:string})?
|
---@param data (string|{[string]:string})?
|
||||||
---@param fn F
|
---@param fn F
|
||||||
|
@ -66,7 +47,7 @@ end
|
||||||
---@param name string
|
---@param name string
|
||||||
---@return string
|
---@return string
|
||||||
function M.normname(name)
|
function M.normname(name)
|
||||||
local ret = name:lower():gsub("^n?vim%-", ""):gsub("%.n?vim$", ""):gsub("[%.%-]lua", ""):gsub("[^a-z]+", "")
|
local ret = name:lower():gsub("^n?vim%-", ""):gsub("%.n?vim$", ""):gsub("%.lua", ""):gsub("[^a-z]+", "")
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -111,10 +92,7 @@ function M.pretty_trace(opts)
|
||||||
return #trace > 0 and ("\n\n# stacktrace:\n" .. table.concat(trace, "\n")) or ""
|
return #trace > 0 and ("\n\n# stacktrace:\n" .. table.concat(trace, "\n")) or ""
|
||||||
end
|
end
|
||||||
|
|
||||||
---@generic R
|
|
||||||
---@param fn fun():R?
|
|
||||||
---@param opts? string|{msg:string, on_error:fun(msg)}
|
---@param opts? string|{msg:string, on_error:fun(msg)}
|
||||||
---@return R
|
|
||||||
function M.try(fn, opts)
|
function M.try(fn, opts)
|
||||||
opts = type(opts) == "string" and { msg = opts } or opts or {}
|
opts = type(opts) == "string" and { msg = opts } or opts or {}
|
||||||
local msg = opts.msg
|
local msg = opts.msg
|
||||||
|
@ -171,9 +149,7 @@ function M.very_lazy()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
vim.g.did_very_lazy = true
|
vim.g.did_very_lazy = true
|
||||||
M.track({ event = "VeryLazy" })
|
|
||||||
vim.api.nvim_exec_autocmds("User", { pattern = "VeryLazy", modeline = false })
|
vim.api.nvim_exec_autocmds("User", { pattern = "VeryLazy", modeline = false })
|
||||||
M.track()
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -245,33 +221,18 @@ function M.walkmods(root, fn, modname)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param modname string
|
---@param modname string
|
||||||
---@return string
|
function M.get_unloaded_rtp(modname)
|
||||||
function M.topmod(modname)
|
modname = modname:gsub("/", ".")
|
||||||
return modname:match("^[^./]+") or modname
|
local idx = modname:find(".", 1, true)
|
||||||
end
|
local topmod = idx and modname:sub(1, idx - 1) or modname
|
||||||
|
topmod = M.normname(topmod)
|
||||||
|
|
||||||
---@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 rtp = {}
|
||||||
local Config = require("lazy.core.config")
|
local Config = require("lazy.core.config")
|
||||||
if Config.spec then
|
if Config.spec then
|
||||||
for _, plugin in pairs(Config.spec.plugins) do
|
for _, plugin in pairs(Config.spec.plugins) do
|
||||||
if not (plugin._.loaded or plugin.module == false or plugin.virtual) then
|
if not (plugin._.loaded or plugin.module == false) then
|
||||||
if norm == M.normname(plugin.name) then
|
if topmod == M.normname(plugin.name) then
|
||||||
table.insert(rtp, 1, plugin.dir)
|
table.insert(rtp, 1, plugin.dir)
|
||||||
else
|
else
|
||||||
table.insert(rtp, plugin.dir)
|
table.insert(rtp, plugin.dir)
|
||||||
|
@ -279,45 +240,31 @@ function M.get_unloaded_rtp(modname, opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
M.unloaded_cache[topmod] = rtp
|
return rtp
|
||||||
return rtp, false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.find_root(modname)
|
function M.find_root(modname)
|
||||||
local paths, cached = M.get_unloaded_rtp(modname, { cache = true })
|
|
||||||
|
|
||||||
local ret = require("lazy.core.cache").find(modname, {
|
local ret = require("lazy.core.cache").find(modname, {
|
||||||
rtp = true,
|
rtp = true,
|
||||||
paths = paths,
|
paths = M.get_unloaded_rtp(modname),
|
||||||
patterns = { ".lua", "" },
|
patterns = { "", ".lua" },
|
||||||
})[1]
|
})[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
|
if ret then
|
||||||
return ret.modpath:gsub("%.lua$", ""), ret.modpath
|
local root = ret.modpath:gsub("/init%.lua$", ""):gsub("%.lua$", "")
|
||||||
|
return root
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param modname string
|
---@param modname string
|
||||||
---@param fn fun(modname:string, modpath:string)
|
---@param fn fun(modname:string, modpath:string)
|
||||||
function M.lsmod(modname, fn)
|
function M.lsmod(modname, fn)
|
||||||
local root, match = M.find_root(modname)
|
local root = M.find_root(modname)
|
||||||
if not root then
|
if not root then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if match:sub(-4) == ".lua" then
|
if vim.uv.fs_stat(root .. ".lua") then
|
||||||
fn(modname, match)
|
fn(modname, root .. ".lua")
|
||||||
if not vim.uv.fs_stat(root) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
M.ls(root, function(path, name, type)
|
M.ls(root, function(path, name, type)
|
||||||
|
@ -374,7 +321,6 @@ function M.notify(msg, opts)
|
||||||
local lang = opts.lang or "markdown"
|
local lang = opts.lang or "markdown"
|
||||||
local n = opts.once and vim.notify_once or vim.notify
|
local n = opts.once and vim.notify_once or vim.notify
|
||||||
n(msg, opts.level or vim.log.levels.INFO, {
|
n(msg, opts.level or vim.log.levels.INFO, {
|
||||||
ft = lang,
|
|
||||||
on_open = function(win)
|
on_open = function(win)
|
||||||
local ok = pcall(function()
|
local ok = pcall(function()
|
||||||
vim.treesitter.language.add("markdown")
|
vim.treesitter.language.add("markdown")
|
||||||
|
@ -482,35 +428,4 @@ function M.lazy_require(module)
|
||||||
})
|
})
|
||||||
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
|
return M
|
||||||
|
|
|
@ -131,8 +131,7 @@ function M.colors(opts)
|
||||||
{ "---", "---", "---" },
|
{ "---", "---", "---" },
|
||||||
}
|
}
|
||||||
Util.foreach(require(opts.modname).colors, function(group, link)
|
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 "" }
|
||||||
lines[#lines + 1] = { "**" .. opts.name .. group .. "**", link, comments[group] or "" }
|
|
||||||
end)
|
end)
|
||||||
return { content = M.table(lines) }
|
return { content = M.table(lines) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -80,8 +80,8 @@ return {
|
||||||
-- you can use a custom url to fetch a plugin
|
-- you can use a custom url to fetch a plugin
|
||||||
{ url = "git@github.com:folke/noice.nvim.git" },
|
{ url = "git@github.com:folke/noice.nvim.git" },
|
||||||
|
|
||||||
-- local plugins can also be configured with the dev option.
|
-- local plugins can also be configure with the dev option.
|
||||||
-- This will use {config.dev.path}/noice.nvim/ instead of fetching it from GitHub
|
-- 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
|
-- With the dev option, you can easily switch between the local and installed version of a plugin
|
||||||
{ "folke/noice.nvim", dev = true },
|
{ "folke/noice.nvim", dev = true },
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
local Config = require("lazy.core.config")
|
local Config = require("lazy.core.config")
|
||||||
local Process = require("lazy.manage.process")
|
|
||||||
local uv = vim.uv or vim.loop
|
local uv = vim.uv or vim.loop
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
@ -9,67 +8,15 @@ local start = vim.health.start or vim.health.report_start
|
||||||
local ok = vim.health.ok or vim.health.report_ok
|
local ok = vim.health.ok or vim.health.report_ok
|
||||||
local warn = vim.health.warn or vim.health.report_warn
|
local warn = vim.health.warn or vim.health.report_warn
|
||||||
local error = vim.health.error or vim.health.report_error
|
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()
|
function M.check()
|
||||||
start("lazy.nvim")
|
start("lazy.nvim")
|
||||||
info("{lazy.nvim} version `" .. Config.version .. "`")
|
|
||||||
|
|
||||||
M.have("git")
|
if vim.fn.executable("git") == 1 then
|
||||||
|
ok("Git installed")
|
||||||
|
else
|
||||||
|
error("Git not installed?")
|
||||||
|
end
|
||||||
|
|
||||||
local sites = vim.opt.packpath:get()
|
local sites = vim.opt.packpath:get()
|
||||||
local default_site = vim.fn.stdpath("data") .. "/site"
|
local default_site = vim.fn.stdpath("data") .. "/site"
|
||||||
|
@ -90,7 +37,7 @@ function M.check()
|
||||||
ok("no existing packages found by other package managers")
|
ok("no existing packages found by other package managers")
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, name in ipairs({ "packer", "plugged", "paq", "pckr", "mini.deps" }) do
|
for _, name in ipairs({ "packer", "plugged", "paq" }) do
|
||||||
for _, path in ipairs(vim.opt.rtp:get()) do
|
for _, path in ipairs(vim.opt.rtp:get()) do
|
||||||
if path:find(name, 1, true) then
|
if path:find(name, 1, true) then
|
||||||
error("Found paths on the rtp from another plugin manager `" .. name .. "`")
|
error("Found paths on the rtp from another plugin manager `" .. name .. "`")
|
||||||
|
@ -112,6 +59,7 @@ function M.check()
|
||||||
else
|
else
|
||||||
for _, plugin in pairs(spec.plugins) do
|
for _, plugin in pairs(spec.plugins) do
|
||||||
M.check_valid(plugin)
|
M.check_valid(plugin)
|
||||||
|
M.check_override(plugin)
|
||||||
end
|
end
|
||||||
if #spec.notifs > 0 then
|
if #spec.notifs > 0 then
|
||||||
error("Issues were reported when loading your specs:")
|
error("Issues were reported when loading your specs:")
|
||||||
|
@ -127,47 +75,6 @@ function M.check()
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
---@param plugin LazyPlugin
|
---@param plugin LazyPlugin
|
||||||
|
@ -181,6 +88,23 @@ function M.check_valid(plugin)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param plugin LazyPlugin
|
||||||
|
function M.check_override(plugin)
|
||||||
|
if not plugin._.super then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local Handler = require("lazy.core.handler")
|
||||||
|
local skip = { "dependencies", "_", "opts", 1 }
|
||||||
|
vim.list_extend(skip, vim.tbl_values(Handler.types))
|
||||||
|
|
||||||
|
for key, value in pairs(plugin._.super) do
|
||||||
|
if not vim.tbl_contains(skip, key) and plugin[key] and plugin[key] ~= value then
|
||||||
|
warn("{" .. plugin.name .. "}: overriding <" .. key .. ">")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
M.valid = {
|
M.valid = {
|
||||||
1,
|
1,
|
||||||
"_",
|
"_",
|
||||||
|
|
|
@ -35,9 +35,7 @@ end
|
||||||
function M.fast_check(opts)
|
function M.fast_check(opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
for _, plugin in pairs(Config.plugins) do
|
for _, plugin in pairs(Config.plugins) do
|
||||||
-- don't check local plugins here, since we mark them as needing updates
|
if not plugin.pin and not plugin.dev and plugin._.installed then
|
||||||
-- 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
|
plugin._.updates = nil
|
||||||
local info = Git.info(plugin.dir)
|
local info = Git.info(plugin.dir)
|
||||||
local ok, target = pcall(Git.get_target, plugin)
|
local ok, target = pcall(Git.get_target, plugin)
|
||||||
|
|
|
@ -116,12 +116,6 @@ end
|
||||||
---@param plugin LazyPlugin
|
---@param plugin LazyPlugin
|
||||||
---@return GitInfo?
|
---@return GitInfo?
|
||||||
function M.get_target(plugin)
|
function M.get_target(plugin)
|
||||||
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))
|
local branch = assert(M.get_branch(plugin))
|
||||||
|
|
||||||
if plugin.commit then
|
if plugin.commit then
|
||||||
|
@ -150,6 +144,7 @@ function M.get_target(plugin)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
---@diagnostic disable-next-line: return-type-mismatch
|
||||||
return { branch = branch, commit = M.get_commit(plugin.dir, branch, true) }
|
return { branch = branch, commit = M.get_commit(plugin.dir, branch, true) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -189,12 +184,7 @@ function M.get_tag_refs(repo, tagref)
|
||||||
tagref = tagref or "--tags"
|
tagref = tagref or "--tags"
|
||||||
---@type table<string,string>
|
---@type table<string,string>
|
||||||
local tags = {}
|
local tags = {}
|
||||||
local ok, lines = pcall(function()
|
local lines = Process.exec({ "git", "show-ref", "-d", tagref }, { cwd = repo })
|
||||||
return Process.exec({ "git", "show-ref", "-d", tagref }, { cwd = repo })
|
|
||||||
end)
|
|
||||||
if not ok then
|
|
||||||
return {}
|
|
||||||
end
|
|
||||||
for _, line in ipairs(lines) do
|
for _, line in ipairs(lines) do
|
||||||
local ref, tag = line:match("^(%w+) refs/tags/([^%^]+)%^?{?}?$")
|
local ref, tag = line:match("^(%w+) refs/tags/([^%^]+)%^?{?}?$")
|
||||||
if ref then
|
if ref then
|
||||||
|
|
|
@ -80,23 +80,14 @@ function M.install(opts)
|
||||||
opts = M.opts(opts, { mode = "install" })
|
opts = M.opts(opts, { mode = "install" })
|
||||||
return M.run({
|
return M.run({
|
||||||
pipeline = {
|
pipeline = {
|
||||||
"plugin.exists",
|
|
||||||
"git.clone",
|
"git.clone",
|
||||||
{ "git.checkout", lockfile = opts.lockfile },
|
{ "git.checkout", lockfile = opts.lockfile },
|
||||||
"plugin.docs",
|
"plugin.docs",
|
||||||
{
|
|
||||||
"wait",
|
"wait",
|
||||||
---@param runner Runner
|
|
||||||
sync = function(runner)
|
|
||||||
require("lazy.pkg").update()
|
|
||||||
Plugin.load()
|
|
||||||
runner:update()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
"plugin.build",
|
"plugin.build",
|
||||||
},
|
},
|
||||||
plugins = function(plugin)
|
plugins = function(plugin)
|
||||||
return not (plugin._.installed and not plugin._.build)
|
return plugin.url and not plugin._.installed
|
||||||
end,
|
end,
|
||||||
}, opts):wait(function()
|
}, opts):wait(function()
|
||||||
require("lazy.manage.lock").update()
|
require("lazy.manage.lock").update()
|
||||||
|
@ -109,22 +100,13 @@ function M.update(opts)
|
||||||
opts = M.opts(opts, { mode = "update" })
|
opts = M.opts(opts, { mode = "update" })
|
||||||
return M.run({
|
return M.run({
|
||||||
pipeline = {
|
pipeline = {
|
||||||
"plugin.exists",
|
|
||||||
"git.origin",
|
"git.origin",
|
||||||
"git.branch",
|
"git.branch",
|
||||||
"git.fetch",
|
"git.fetch",
|
||||||
"git.status",
|
"git.status",
|
||||||
{ "git.checkout", lockfile = opts.lockfile },
|
{ "git.checkout", lockfile = opts.lockfile },
|
||||||
"plugin.docs",
|
"plugin.docs",
|
||||||
{
|
|
||||||
"wait",
|
"wait",
|
||||||
---@param runner Runner
|
|
||||||
sync = function(runner)
|
|
||||||
require("lazy.pkg").update()
|
|
||||||
Plugin.load()
|
|
||||||
runner:update()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
"plugin.build",
|
"plugin.build",
|
||||||
{ "git.log", updated = true },
|
{ "git.log", updated = true },
|
||||||
},
|
},
|
||||||
|
@ -149,7 +131,6 @@ function M.check(opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
return M.run({
|
return M.run({
|
||||||
pipeline = {
|
pipeline = {
|
||||||
"plugin.exists",
|
|
||||||
{ "git.origin", check = true },
|
{ "git.origin", check = true },
|
||||||
"git.fetch",
|
"git.fetch",
|
||||||
"git.status",
|
"git.status",
|
||||||
|
@ -239,7 +220,7 @@ function M.clear(plugins)
|
||||||
if plugin._.tasks then
|
if plugin._.tasks then
|
||||||
---@param task LazyTask
|
---@param task LazyTask
|
||||||
plugin._.tasks = vim.tbl_filter(function(task)
|
plugin._.tasks = vim.tbl_filter(function(task)
|
||||||
return task:running() or task:has_errors()
|
return task:is_running()
|
||||||
end, plugin._.tasks)
|
end, plugin._.tasks)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,53 +3,50 @@ local Git = require("lazy.manage.git")
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
---@alias LazyLockfile table<string, {commit:string, branch:string}>
|
---@type table<string, {commit:string, branch:string}>
|
||||||
---@type LazyLockfile
|
|
||||||
M.lock = {}
|
M.lock = {}
|
||||||
M._loaded = false
|
M._loaded = false
|
||||||
|
|
||||||
function M.update()
|
function M.update()
|
||||||
M.load()
|
|
||||||
vim.fn.mkdir(vim.fn.fnamemodify(Config.options.lockfile, ":p:h"), "p")
|
vim.fn.mkdir(vim.fn.fnamemodify(Config.options.lockfile, ":p:h"), "p")
|
||||||
local f = assert(io.open(Config.options.lockfile, "wb"))
|
local f = assert(io.open(Config.options.lockfile, "wb"))
|
||||||
f:write("{\n")
|
f:write("{\n")
|
||||||
|
M.lock = {}
|
||||||
|
|
||||||
-- keep disabled and cond plugins
|
---@param plugin LazyPlugin
|
||||||
for name in pairs(M.lock) do
|
local plugins = vim.tbl_filter(function(plugin)
|
||||||
if not (Config.spec.disabled[name] or Config.spec.ignore_installed[name]) then
|
return not plugin._.is_local and plugin._.installed
|
||||||
M.lock[name] = nil
|
end, Config.plugins)
|
||||||
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[]
|
---@type string[]
|
||||||
local names = vim.tbl_keys(M.lock)
|
local names = vim.tbl_map(function(plugin)
|
||||||
|
return plugin.name
|
||||||
|
end, plugins)
|
||||||
table.sort(names)
|
table.sort(names)
|
||||||
|
|
||||||
for n, name in ipairs(names) do
|
for n, name in ipairs(names) do
|
||||||
local info = M.lock[name]
|
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
|
||||||
|
info.branch = assert(Git.get_branch(plugin))
|
||||||
|
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))
|
f:write(([[ %q: { "branch": %q, "commit": %q }]]):format(name, info.branch, info.commit))
|
||||||
if n ~= #names then
|
if n ~= #names then
|
||||||
f:write(",\n")
|
f:write(",\n")
|
||||||
end
|
end
|
||||||
|
---@diagnostic disable-next-line: assign-type-mismatch
|
||||||
|
M.lock[plugin.name] = info
|
||||||
end
|
end
|
||||||
f:write("\n}\n")
|
end
|
||||||
|
f:write("\n}")
|
||||||
f:close()
|
f:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.load()
|
function M.load()
|
||||||
if M._loaded then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
M.lock = {}
|
M.lock = {}
|
||||||
M._loaded = true
|
M._loaded = true
|
||||||
local f = io.open(Config.options.lockfile, "r")
|
local f = io.open(Config.options.lockfile, "r")
|
||||||
|
@ -67,7 +64,9 @@ end
|
||||||
---@param plugin LazyPlugin
|
---@param plugin LazyPlugin
|
||||||
---@return {commit:string, branch:string}
|
---@return {commit:string, branch:string}
|
||||||
function M.get(plugin)
|
function M.get(plugin)
|
||||||
|
if not M._loaded then
|
||||||
M.load()
|
M.load()
|
||||||
|
end
|
||||||
return M.lock[plugin.name]
|
return M.lock[plugin.name]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,133 +1,66 @@
|
||||||
local Async = require("lazy.async")
|
|
||||||
local Config = require("lazy.core.config")
|
local Config = require("lazy.core.config")
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
---@type table<uv_process_t, true>
|
||||||
|
M.running = {}
|
||||||
|
|
||||||
|
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",
|
||||||
|
}
|
||||||
|
|
||||||
---@diagnostic disable-next-line: no-unknown
|
---@diagnostic disable-next-line: no-unknown
|
||||||
local uv = vim.uv
|
local uv = vim.uv
|
||||||
|
|
||||||
---@class ProcessOpts
|
---@class ProcessOpts
|
||||||
---@field args string[]
|
---@field args string[]
|
||||||
---@field cwd? string
|
---@field cwd? string
|
||||||
---@field on_line? fun(line:string)
|
---@field on_line? fun(string)
|
||||||
---@field on_exit? fun(ok:boolean, output:string)
|
---@field on_exit? fun(ok:boolean, output:string)
|
||||||
---@field on_data? fun(data:string, is_stderr?:boolean)
|
|
||||||
---@field timeout? number
|
---@field timeout? number
|
||||||
---@field env? table<string,string>
|
---@field env? table<string,string>
|
||||||
|
|
||||||
local M = {}
|
|
||||||
|
|
||||||
---@type table<uv_process_t, LazyProcess>
|
|
||||||
M.running = setmetatable({}, { __mode = "k" })
|
|
||||||
|
|
||||||
---@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
|
---@param opts? ProcessOpts
|
||||||
function Process.new(cmd, opts)
|
---@param cmd string
|
||||||
local self = setmetatable({}, { __index = Process })
|
function M.spawn(cmd, opts)
|
||||||
---@async
|
|
||||||
Process.init(self, function()
|
|
||||||
self:_run()
|
|
||||||
end)
|
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
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)
|
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
|
|
||||||
|
|
||||||
---@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 = 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()
|
|
||||||
self:resume()
|
|
||||||
end)
|
|
||||||
|
|
||||||
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>
|
---@type table<string, string>
|
||||||
local env = vim.tbl_extend("force", {
|
local env = vim.tbl_extend("force", {
|
||||||
GIT_SSH_COMMAND = "ssh -oBatchMode=yes",
|
GIT_SSH_COMMAND = "ssh -oBatchMode=yes",
|
||||||
}, uv.os_environ(), self.opts.env or {})
|
}, uv.os_environ(), opts.env or {})
|
||||||
env.GIT_DIR = nil
|
env.GIT_DIR = nil
|
||||||
env.GIT_WORK_TREE = nil
|
env.GIT_WORK_TREE = nil
|
||||||
env.GIT_TERMINAL_PROMPT = "0"
|
env.GIT_TERMINAL_PROMPT = "0"
|
||||||
|
@ -138,102 +71,128 @@ function Process:env()
|
||||||
for k, v in pairs(env) do
|
for k, v in pairs(env) do
|
||||||
env_flat[#env_flat + 1] = k .. "=" .. v
|
env_flat[#env_flat + 1] = k .. "=" .. v
|
||||||
end
|
end
|
||||||
return env_flat
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param signals uv.aliases.signals|uv.aliases.signals[]|nil
|
local stdout = assert(uv.new_pipe())
|
||||||
function Process:kill(signals)
|
local stderr = assert(uv.new_pipe())
|
||||||
if not self.handle or self.handle:is_closing() then
|
|
||||||
return
|
local output = ""
|
||||||
end
|
---@type uv_process_t?
|
||||||
signals = signals or { "sigterm", "sigkill" }
|
local handle = nil
|
||||||
signals = type(signals) == "table" and signals or { signals }
|
|
||||||
---@cast signals uv.aliases.signals[]
|
---@type uv_timer_t
|
||||||
local timer = assert(uv.new_timer())
|
local timeout
|
||||||
timer:start(0, 1000, function()
|
local killed = false
|
||||||
if self.handle and not self.handle:is_closing() and #signals > 0 then
|
if opts.timeout then
|
||||||
self.handle:kill(table.remove(signals, 1))
|
timeout = assert(uv.new_timer())
|
||||||
else
|
timeout:start(opts.timeout, 0, function()
|
||||||
timer:stop()
|
if M.kill(handle) then
|
||||||
|
killed = true
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param err? string
|
-- make sure the cwd is valid
|
||||||
---@param data? string
|
if not opts.cwd and type(uv.cwd()) ~= "string" then
|
||||||
---@param is_stderr? boolean
|
opts.cwd = uv.os_homedir()
|
||||||
function Process:on_data(err, data, is_stderr)
|
end
|
||||||
assert(not err, err)
|
|
||||||
if not data then
|
handle = uv.spawn(cmd, {
|
||||||
|
stdio = { nil, stdout, stderr },
|
||||||
|
args = opts.args,
|
||||||
|
cwd = opts.cwd,
|
||||||
|
env = env_flat,
|
||||||
|
}, function(exit_code, signal)
|
||||||
|
---@cast handle uv_process_t
|
||||||
|
M.running[handle] = nil
|
||||||
|
if timeout then
|
||||||
|
timeout:stop()
|
||||||
|
timeout:close()
|
||||||
|
end
|
||||||
|
handle:close()
|
||||||
|
stdout:close()
|
||||||
|
stderr:close()
|
||||||
|
local check = assert(uv.new_check())
|
||||||
|
check:start(function()
|
||||||
|
if not stdout:is_closing() or not stderr:is_closing() then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
check:stop()
|
||||||
if self.opts.on_data then
|
if opts.on_exit then
|
||||||
self.opts.on_data(data, is_stderr)
|
output = output:gsub("[^\r\n]+\r", "")
|
||||||
|
if killed then
|
||||||
|
output = output .. "\n" .. "Process was killed because it reached the timeout"
|
||||||
|
elseif signal ~= 0 then
|
||||||
|
output = output .. "\n" .. "Process was killed with SIG" .. M.signals[signal]
|
||||||
end
|
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")
|
|
||||||
|
|
||||||
if self.opts.on_line then
|
vim.schedule(function()
|
||||||
self.opts.on_line(lines[#lines])
|
opts.on_exit(exit_code == 0 and signal == 0, output)
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
if not handle then
|
||||||
|
if opts.on_exit then
|
||||||
|
opts.on_exit(false, "Failed to spawn process " .. cmd .. " " .. vim.inspect(opts))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
M.running[handle] = true
|
||||||
|
|
||||||
|
---@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
|
||||||
|
end
|
||||||
|
|
||||||
|
uv.read_start(stdout, on_output)
|
||||||
|
uv.read_start(stderr, on_output)
|
||||||
|
|
||||||
|
return handle
|
||||||
end
|
end
|
||||||
|
|
||||||
M.signals = {
|
function M.kill(handle)
|
||||||
"hup",
|
if handle and not handle:is_closing() then
|
||||||
"int",
|
M.running[handle] = nil
|
||||||
"quit",
|
uv.process_kill(handle, "sigint")
|
||||||
"ill",
|
return true
|
||||||
"trap",
|
end
|
||||||
"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
|
end
|
||||||
|
|
||||||
function M.abort()
|
function M.abort()
|
||||||
for _, proc in pairs(M.running) do
|
for handle in pairs(M.running) do
|
||||||
proc:kill()
|
M.kill(handle)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@async
|
---@param cmd string[]
|
||||||
---@param cmd string|string[]
|
---@param opts? {cwd:string, env:table}
|
||||||
---@param opts? ProcessOpts
|
|
||||||
function M.exec(cmd, opts)
|
function M.exec(cmd, opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
local proc = M.spawn(cmd, opts)
|
---@type string[]
|
||||||
proc:wait()
|
local lines
|
||||||
return vim.split(proc.data, "\n"), proc.code
|
local job = vim.fn.jobstart(cmd, {
|
||||||
|
cwd = opts.cwd,
|
||||||
|
pty = false,
|
||||||
|
env = opts.env,
|
||||||
|
stdout_buffered = true,
|
||||||
|
on_stdout = function(_, _lines)
|
||||||
|
lines = _lines
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
vim.fn.jobwait({ job })
|
||||||
|
return lines
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|
|
@ -84,12 +84,6 @@ function M.check(start)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not (start or #changes == 0) then
|
if not (start or #changes == 0) then
|
||||||
M.reload(changes)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param {file:string, what:string}[]
|
|
||||||
function M.reload(changes)
|
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
if Config.options.change_detection.notify and not Config.headless() then
|
if Config.options.change_detection.notify and not Config.headless() then
|
||||||
local lines = { "# Config Change Detected. Reloading...", "" }
|
local lines = { "# Config Change Detected. Reloading...", "" }
|
||||||
|
@ -102,6 +96,7 @@ function M.reload(changes)
|
||||||
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
|
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
|
||||||
vim.api.nvim_exec_autocmds("User", { pattern = "LazyReload", modeline = false })
|
vim.api.nvim_exec_autocmds("User", { pattern = "LazyReload", modeline = false })
|
||||||
end)
|
end)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|
|
@ -1,23 +1,21 @@
|
||||||
local Async = require("lazy.async")
|
|
||||||
local Config = require("lazy.core.config")
|
local Config = require("lazy.core.config")
|
||||||
local Task = require("lazy.manage.task")
|
local Task = require("lazy.manage.task")
|
||||||
|
local Util = require("lazy.util")
|
||||||
|
|
||||||
---@class RunnerOpts
|
---@class RunnerOpts
|
||||||
---@field pipeline (string|{[1]:string, [string]:any})[]
|
---@field pipeline (string|{[1]:string, [string]:any})[]
|
||||||
---@field plugins? LazyPlugin[]|fun(plugin:LazyPlugin):any?
|
---@field plugins? LazyPlugin[]|fun(plugin:LazyPlugin):any?
|
||||||
---@field concurrency? number
|
---@field concurrency? number
|
||||||
|
|
||||||
---@class RunnerTask
|
---@alias PipelineStep {task:string, opts?:TaskOptions}
|
||||||
---@field task? LazyTask
|
---@alias LazyRunnerTask {co:thread, status: {task?:LazyTask, waiting?:boolean}, plugin: LazyPlugin}
|
||||||
---@field step number
|
|
||||||
|
|
||||||
---@alias PipelineStep {task:string, opts?:TaskOptions }
|
|
||||||
|
|
||||||
---@class Runner
|
---@class Runner
|
||||||
---@field _plugins table<string,LazyPlugin>
|
---@field _plugins LazyPlugin[]
|
||||||
|
---@field _running LazyRunnerTask[]
|
||||||
---@field _pipeline PipelineStep[]
|
---@field _pipeline PipelineStep[]
|
||||||
|
---@field _on_done fun()[]
|
||||||
---@field _opts RunnerOpts
|
---@field _opts RunnerOpts
|
||||||
---@field _running? Async
|
|
||||||
local Runner = {}
|
local Runner = {}
|
||||||
|
|
||||||
---@param opts RunnerOpts
|
---@param opts RunnerOpts
|
||||||
|
@ -26,17 +24,16 @@ function Runner.new(opts)
|
||||||
self._opts = opts or {}
|
self._opts = opts or {}
|
||||||
|
|
||||||
local plugins = self._opts.plugins
|
local plugins = self._opts.plugins
|
||||||
---@type LazyPlugin[]
|
|
||||||
local pp = {}
|
|
||||||
if type(plugins) == "function" then
|
if type(plugins) == "function" then
|
||||||
pp = vim.tbl_filter(plugins, Config.plugins)
|
self._plugins = vim.tbl_filter(plugins, Config.plugins)
|
||||||
else
|
else
|
||||||
pp = plugins or Config.plugins
|
self._plugins = plugins or Config.plugins
|
||||||
end
|
|
||||||
self._plugins = {}
|
|
||||||
for _, plugin in ipairs(pp) do
|
|
||||||
self._plugins[plugin.name] = plugin
|
|
||||||
end
|
end
|
||||||
|
table.sort(self._plugins, function(a, b)
|
||||||
|
return a.name < b.name
|
||||||
|
end)
|
||||||
|
self._running = {}
|
||||||
|
self._on_done = {}
|
||||||
|
|
||||||
---@param step string|(TaskOptions|{[1]:string})
|
---@param step string|(TaskOptions|{[1]:string})
|
||||||
self._pipeline = vim.tbl_map(function(step)
|
self._pipeline = vim.tbl_map(function(step)
|
||||||
|
@ -46,152 +43,130 @@ function Runner.new(opts)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function Runner:plugin(name)
|
---@param entry LazyRunnerTask
|
||||||
return self._plugins[name]
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Update plugins
|
function Runner:resume(waiting)
|
||||||
function Runner:update()
|
if waiting then
|
||||||
for name in pairs(self._plugins) do
|
for _, entry in ipairs(self._running) do
|
||||||
self._plugins[name] = Config.plugins[name] or self._plugins[name]
|
if entry.status then
|
||||||
|
if entry.status.waiting then
|
||||||
|
entry.status.waiting = false
|
||||||
|
entry.plugin._.working = true
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local running = 0
|
||||||
|
for _, entry in ipairs(self._running) do
|
||||||
|
if entry.status then
|
||||||
|
if not entry.status.waiting and self:_resume(entry) then
|
||||||
|
running = running + 1
|
||||||
|
if self._opts.concurrency and running >= self._opts.concurrency then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return running > 0 or (not waiting and self:resume(true))
|
||||||
end
|
end
|
||||||
|
|
||||||
function Runner:start()
|
function Runner:start()
|
||||||
---@async
|
for _, plugin in pairs(self._plugins) do
|
||||||
self._running = Async.new(function()
|
local co = coroutine.create(self.run_pipeline)
|
||||||
self:_start()
|
local ok, err = coroutine.resume(co, self, plugin)
|
||||||
|
if ok then
|
||||||
|
table.insert(self._running, { co = co, status = {}, plugin = plugin })
|
||||||
|
else
|
||||||
|
Util.error("Could not start tasks for " .. plugin.name .. "\n" .. err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local check = vim.uv.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 = {}
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@async
|
---@async
|
||||||
function Runner:_start()
|
---@param plugin LazyPlugin
|
||||||
---@type string[]
|
function Runner:run_pipeline(plugin)
|
||||||
local names = vim.tbl_keys(self._plugins)
|
plugin._.working = true
|
||||||
table.sort(names)
|
coroutine.yield()
|
||||||
|
for _, step in ipairs(self._pipeline) do
|
||||||
---@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
|
if step.task == "wait" then
|
||||||
plugin._.working = false
|
plugin._.working = false
|
||||||
waiting = waiting + 1
|
coroutine.yield({ waiting = true })
|
||||||
wait_step = s.step
|
|
||||||
break
|
|
||||||
else
|
|
||||||
s.task = self:queue(plugin, step)
|
|
||||||
plugin._.working = true
|
plugin._.working = true
|
||||||
if s.task then
|
else
|
||||||
active = active + 1
|
local task = self:queue(plugin, step.task, step.opts)
|
||||||
s.task:wake(false)
|
if task then
|
||||||
break
|
coroutine.yield({ task = task })
|
||||||
|
assert(task:is_done())
|
||||||
|
if task.error then
|
||||||
|
plugin._.working = false
|
||||||
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
plugin._.working = false
|
||||||
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
|
end
|
||||||
|
|
||||||
---@param plugin LazyPlugin
|
---@param plugin LazyPlugin
|
||||||
---@param step PipelineStep
|
---@param task_name string
|
||||||
|
---@param opts? TaskOptions
|
||||||
---@return LazyTask?
|
---@return LazyTask?
|
||||||
function Runner:queue(plugin, step)
|
function Runner:queue(plugin, task_name, opts)
|
||||||
assert(self._running and self._running:running(), "Runner is not running")
|
assert(self._running)
|
||||||
local def = vim.split(step.task, ".", { plain = true })
|
local def = vim.split(task_name, ".", { plain = true })
|
||||||
---@type LazyTaskDef
|
---@type LazyTaskDef
|
||||||
local task_def = require("lazy.manage.task." .. def[1])[def[2]]
|
local task_def = require("lazy.manage.task." .. def[1])[def[2]]
|
||||||
assert(task_def, "Task not found: " .. step.task)
|
assert(task_def)
|
||||||
local opts = step.opts or {}
|
opts = opts or {}
|
||||||
if not (task_def.skip and task_def.skip(plugin, opts)) then
|
if not (task_def.skip and task_def.skip(plugin, opts)) then
|
||||||
return Task.new(plugin, def[2], task_def.run, opts)
|
local task = Task.new(plugin, def[2], task_def.run, opts)
|
||||||
|
task:start()
|
||||||
|
return task
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Runner:is_running()
|
|
||||||
return self._running and self._running:running()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Execute the callback async when done.
|
-- Execute the callback async when done.
|
||||||
-- When no callback is specified, this will wait sync
|
-- When no callback is specified, this will wait sync
|
||||||
---@param cb? fun()
|
---@param cb? fun()
|
||||||
function Runner:wait(cb)
|
function Runner:wait(cb)
|
||||||
if not self:is_running() then
|
if #self._running == 0 then
|
||||||
if cb then
|
if cb then
|
||||||
cb()
|
cb()
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
if cb then
|
if cb then
|
||||||
self._running:on("done", cb)
|
table.insert(self._on_done, cb)
|
||||||
else
|
else
|
||||||
self._running:wait()
|
-- sync wait
|
||||||
|
while #self._running > 0 do
|
||||||
|
vim.wait(10)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,6 @@ local M = {}
|
||||||
---@field patch number
|
---@field patch number
|
||||||
---@field prerelease? string
|
---@field prerelease? string
|
||||||
---@field build? string
|
---@field build? string
|
||||||
---@field input? string
|
|
||||||
local Semver = {}
|
local Semver = {}
|
||||||
Semver.__index = Semver
|
Semver.__index = Semver
|
||||||
|
|
||||||
|
@ -91,7 +90,6 @@ function M.version(version)
|
||||||
patch = patch == "" and 0 or tonumber(patch),
|
patch = patch == "" and 0 or tonumber(patch),
|
||||||
prerelease = prerelease ~= "" and prerelease or nil,
|
prerelease = prerelease ~= "" and prerelease or nil,
|
||||||
build = build ~= "" and build or nil,
|
build = build ~= "" and build or nil,
|
||||||
input = version,
|
|
||||||
}, Semver)
|
}, Semver)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,9 +4,17 @@ local Util = require("lazy.util")
|
||||||
---@type table<string, LazyTaskDef>
|
---@type table<string, LazyTaskDef>
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local function rm(dir)
|
M.clean = {
|
||||||
|
skip = function(plugin)
|
||||||
|
return plugin._.is_local
|
||||||
|
end,
|
||||||
|
run = function(self)
|
||||||
|
local dir = self.plugin.dir:gsub("/+$", "")
|
||||||
|
assert(dir:find(Config.options.root, 1, true) == 1, self.plugin.dir .. " should be under packpath!")
|
||||||
|
|
||||||
local stat = vim.uv.fs_lstat(dir)
|
local stat = vim.uv.fs_lstat(dir)
|
||||||
assert(stat and stat.type == "directory", dir .. " should be a directory!")
|
assert(stat and stat.type == "directory", self.plugin.dir .. " should be a directory!")
|
||||||
|
|
||||||
Util.walk(dir, function(path, _, type)
|
Util.walk(dir, function(path, _, type)
|
||||||
if type == "directory" then
|
if type == "directory" then
|
||||||
vim.uv.fs_rmdir(path)
|
vim.uv.fs_rmdir(path)
|
||||||
|
@ -15,28 +23,6 @@ local function rm(dir)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
vim.uv.fs_rmdir(dir)
|
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
|
self.plugin._.installed = false
|
||||||
end,
|
end,
|
||||||
|
|
|
@ -1,54 +1,8 @@
|
||||||
local Async = require("lazy.async")
|
|
||||||
local Config = require("lazy.core.config")
|
local Config = require("lazy.core.config")
|
||||||
local Git = require("lazy.manage.git")
|
local Git = require("lazy.manage.git")
|
||||||
local Lock = require("lazy.manage.lock")
|
local Lock = require("lazy.manage.lock")
|
||||||
local Util = require("lazy.util")
|
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>
|
---@type table<string, LazyTaskDef>
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
@ -64,10 +18,8 @@ M.log = {
|
||||||
local stat = vim.uv.fs_stat(plugin.dir .. "/.git")
|
local stat = vim.uv.fs_stat(plugin.dir .. "/.git")
|
||||||
return not (stat and stat.type == "directory")
|
return not (stat and stat.type == "directory")
|
||||||
end,
|
end,
|
||||||
---@async
|
|
||||||
---@param opts {args?: string[], updated?:boolean, check?:boolean}
|
---@param opts {args?: string[], updated?:boolean, check?:boolean}
|
||||||
run = function(self, opts)
|
run = function(self, opts)
|
||||||
-- self:spawn({ "sleep", "5" })
|
|
||||||
local args = {
|
local args = {
|
||||||
"log",
|
"log",
|
||||||
"--pretty=format:%h %s (%cr)",
|
"--pretty=format:%h %s (%cr)",
|
||||||
|
@ -78,13 +30,11 @@ M.log = {
|
||||||
"--no-show-signature",
|
"--no-show-signature",
|
||||||
}
|
}
|
||||||
|
|
||||||
local info, target
|
|
||||||
|
|
||||||
if opts.updated then
|
if opts.updated then
|
||||||
table.insert(args, self.plugin._.updated.from .. ".." .. (self.plugin._.updated.to or "HEAD"))
|
table.insert(args, self.plugin._.updated.from .. ".." .. (self.plugin._.updated.to or "HEAD"))
|
||||||
elseif opts.check then
|
elseif opts.check then
|
||||||
info = assert(Git.info(self.plugin.dir))
|
local info = assert(Git.info(self.plugin.dir))
|
||||||
target = assert(Git.get_target(self.plugin))
|
local target = assert(Git.get_target(self.plugin))
|
||||||
if not target.commit then
|
if not target.commit then
|
||||||
for k, v in pairs(target) do
|
for k, v in pairs(target) do
|
||||||
error(k .. " '" .. v .. "' not found")
|
error(k .. " '" .. v .. "' not found")
|
||||||
|
@ -92,7 +42,6 @@ M.log = {
|
||||||
error("no target commit found")
|
error("no target commit found")
|
||||||
end
|
end
|
||||||
assert(target.commit, self.plugin.name .. " " .. target.branch)
|
assert(target.commit, self.plugin.name .. " " .. target.branch)
|
||||||
if not self.plugin._.is_local then
|
|
||||||
if Git.eq(info, target) then
|
if Git.eq(info, target) then
|
||||||
if Config.options.checker.check_pinned then
|
if Config.options.checker.check_pinned then
|
||||||
local last_commit = Git.get_commit(self.plugin.dir, target.branch, true)
|
local last_commit = Git.get_commit(self.plugin.dir, target.branch, true)
|
||||||
|
@ -103,7 +52,6 @@ M.log = {
|
||||||
else
|
else
|
||||||
self.plugin._.updates = { from = info, to = target }
|
self.plugin._.updates = { from = info, to = target }
|
||||||
end
|
end
|
||||||
end
|
|
||||||
table.insert(args, info.commit .. ".." .. target.commit)
|
table.insert(args, info.commit .. ".." .. target.commit)
|
||||||
else
|
else
|
||||||
vim.list_extend(args, opts.args or Config.options.git.log)
|
vim.list_extend(args, opts.args or Config.options.git.log)
|
||||||
|
@ -113,14 +61,6 @@ M.log = {
|
||||||
args = args,
|
args = args,
|
||||||
cwd = self.plugin.dir,
|
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,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,9 +68,7 @@ M.clone = {
|
||||||
skip = function(plugin)
|
skip = function(plugin)
|
||||||
return plugin._.installed or plugin._.is_local
|
return plugin._.installed or plugin._.is_local
|
||||||
end,
|
end,
|
||||||
---@async
|
|
||||||
run = function(self)
|
run = function(self)
|
||||||
throttle.wait()
|
|
||||||
local args = {
|
local args = {
|
||||||
"clone",
|
"clone",
|
||||||
self.plugin.url,
|
self.plugin.url,
|
||||||
|
@ -189,9 +127,8 @@ M.branch = {
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
local branch = assert(Git.get_branch(plugin))
|
local branch = assert(Git.get_branch(plugin))
|
||||||
return Git.get_commit(plugin.dir, branch, true)
|
return Git.get_commit(plugin.dir, branch)
|
||||||
end,
|
end,
|
||||||
---@async
|
|
||||||
run = function(self)
|
run = function(self)
|
||||||
local args = {
|
local args = {
|
||||||
"remote",
|
"remote",
|
||||||
|
@ -217,17 +154,14 @@ M.origin = {
|
||||||
local origin = Git.get_origin(plugin.dir)
|
local origin = Git.get_origin(plugin.dir)
|
||||||
return origin == plugin.url
|
return origin == plugin.url
|
||||||
end,
|
end,
|
||||||
---@async
|
|
||||||
---@param opts {check?:boolean}
|
---@param opts {check?:boolean}
|
||||||
run = function(self, opts)
|
run = function(self, opts)
|
||||||
if opts.check then
|
if opts.check then
|
||||||
local origin = Git.get_origin(self.plugin.dir)
|
local origin = Git.get_origin(self.plugin.dir)
|
||||||
self:error({
|
self.error = "Origin has changed:\n"
|
||||||
"Origin has changed:",
|
self.error = self.error .. " * old: " .. origin .. "\n"
|
||||||
" * old: " .. origin,
|
self.error = self.error .. " * new: " .. self.plugin.url .. "\n"
|
||||||
" * new: " .. self.plugin.url,
|
self.error = self.error .. "Please run update to fix"
|
||||||
"Please run update to fix",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
require("lazy.manage.task.fs").clean.run(self, opts)
|
require("lazy.manage.task.fs").clean.run(self, opts)
|
||||||
|
@ -239,7 +173,6 @@ M.status = {
|
||||||
skip = function(plugin)
|
skip = function(plugin)
|
||||||
return not plugin._.installed or plugin._.is_local
|
return not plugin._.installed or plugin._.is_local
|
||||||
end,
|
end,
|
||||||
---@async
|
|
||||||
run = function(self)
|
run = function(self)
|
||||||
self:spawn("git", {
|
self:spawn("git", {
|
||||||
args = { "ls-files", "-d", "-m" },
|
args = { "ls-files", "-d", "-m" },
|
||||||
|
@ -247,7 +180,6 @@ M.status = {
|
||||||
on_exit = function(ok, output)
|
on_exit = function(ok, output)
|
||||||
if ok then
|
if ok then
|
||||||
local lines = vim.split(output, "\n")
|
local lines = vim.split(output, "\n")
|
||||||
---@type string[]
|
|
||||||
lines = vim.tbl_filter(function(line)
|
lines = vim.tbl_filter(function(line)
|
||||||
-- Fix doc/tags being marked as modified
|
-- Fix doc/tags being marked as modified
|
||||||
if line:gsub("[\\/]", "/") == "doc/tags" then
|
if line:gsub("[\\/]", "/") == "doc/tags" then
|
||||||
|
@ -258,13 +190,12 @@ M.status = {
|
||||||
return line ~= ""
|
return line ~= ""
|
||||||
end, lines)
|
end, lines)
|
||||||
if #lines > 0 then
|
if #lines > 0 then
|
||||||
local msg = { "You have local changes in `" .. self.plugin.dir .. "`:" }
|
self.error = "You have local changes in `" .. self.plugin.dir .. "`:\n"
|
||||||
for _, line in ipairs(lines) do
|
for _, line in ipairs(lines) do
|
||||||
msg[#msg + 1] = " * " .. line
|
self.error = self.error .. " * " .. line .. "\n"
|
||||||
end
|
end
|
||||||
msg[#msg + 1] = "Please remove them to update."
|
self.error = self.error .. "Please remove them to update.\n"
|
||||||
msg[#msg + 1] = "You can also press `x` to remove the plugin and then `I` to install it again."
|
self.error = self.error .. "You can also press `x` to remove the plugin and then `I` to install it again."
|
||||||
self:error(msg)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
@ -275,12 +206,10 @@ M.status = {
|
||||||
-- fetches all needed origin branches
|
-- fetches all needed origin branches
|
||||||
M.fetch = {
|
M.fetch = {
|
||||||
skip = function(plugin)
|
skip = function(plugin)
|
||||||
return not plugin._.installed or plugin._.is_local or cooldown(plugin)
|
return not plugin._.installed or plugin._.is_local
|
||||||
end,
|
end,
|
||||||
|
|
||||||
---@async
|
|
||||||
run = function(self)
|
run = function(self)
|
||||||
throttle.wait()
|
|
||||||
local args = {
|
local args = {
|
||||||
"fetch",
|
"fetch",
|
||||||
"--recurse-submodules",
|
"--recurse-submodules",
|
||||||
|
@ -296,11 +225,6 @@ M.fetch = {
|
||||||
self:spawn("git", {
|
self:spawn("git", {
|
||||||
args = args,
|
args = args,
|
||||||
cwd = self.plugin.dir,
|
cwd = self.plugin.dir,
|
||||||
on_exit = function(ok)
|
|
||||||
if ok then
|
|
||||||
self.plugin._.last_check = vim.uv.now()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
@ -312,10 +236,8 @@ M.checkout = {
|
||||||
return not plugin._.installed or plugin._.is_local
|
return not plugin._.installed or plugin._.is_local
|
||||||
end,
|
end,
|
||||||
|
|
||||||
---@async
|
|
||||||
---@param opts {lockfile?:boolean}
|
---@param opts {lockfile?:boolean}
|
||||||
run = function(self, opts)
|
run = function(self, opts)
|
||||||
throttle.wait()
|
|
||||||
local info = assert(Git.info(self.plugin.dir))
|
local info = assert(Git.info(self.plugin.dir))
|
||||||
local target = assert(Git.get_target(self.plugin))
|
local target = assert(Git.get_target(self.plugin))
|
||||||
|
|
||||||
|
@ -335,7 +257,7 @@ M.checkout = {
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- don't run checkout if target is already reached.
|
-- dont run checkout if target is already reached.
|
||||||
-- unless we just cloned, since then we won't have any data yet
|
-- unless we just cloned, since then we won't have any data yet
|
||||||
if Git.eq(info, target) and info.branch == target.branch then
|
if Git.eq(info, target) and info.branch == target.branch then
|
||||||
self.plugin._.updated = {
|
self.plugin._.updated = {
|
||||||
|
|
|
@ -1,29 +1,23 @@
|
||||||
local Async = require("lazy.async")
|
|
||||||
local Config = require("lazy.core.config")
|
|
||||||
local Process = require("lazy.manage.process")
|
local Process = require("lazy.manage.process")
|
||||||
local Terminal = require("lazy.terminal")
|
|
||||||
|
|
||||||
local colors = Config.options.headless.colors
|
|
||||||
|
|
||||||
---@class LazyTaskDef
|
---@class LazyTaskDef
|
||||||
---@field skip? fun(plugin:LazyPlugin, opts?:TaskOptions):any?
|
---@field skip? fun(plugin:LazyPlugin, opts?:TaskOptions):any?
|
||||||
---@field run async fun(task:LazyTask, opts:TaskOptions)
|
---@field run fun(task:LazyTask, opts:TaskOptions)
|
||||||
|
|
||||||
---@alias LazyTaskFn async fun(task:LazyTask, opts:TaskOptions)
|
---@alias LazyTaskState fun():boolean?
|
||||||
|
|
||||||
---@class LazyMsg
|
---@class LazyTask
|
||||||
---@field msg string
|
|
||||||
---@field level? number
|
|
||||||
|
|
||||||
---@class LazyTask: Async
|
|
||||||
---@field plugin LazyPlugin
|
---@field plugin LazyPlugin
|
||||||
---@field name string
|
---@field name string
|
||||||
---@field private _log LazyMsg[]
|
---@field output string
|
||||||
---@field private _started number
|
---@field status string
|
||||||
|
---@field error? string
|
||||||
|
---@field private _task fun(task:LazyTask)
|
||||||
|
---@field private _running LazyPluginState[]
|
||||||
|
---@field private _started? number
|
||||||
---@field private _ended? number
|
---@field private _ended? number
|
||||||
---@field private _opts TaskOptions
|
---@field private _opts TaskOptions
|
||||||
---@field private _level number
|
local Task = {}
|
||||||
local Task = setmetatable({}, { __index = Async.Async })
|
|
||||||
|
|
||||||
---@class TaskOptions: {[string]:any}
|
---@class TaskOptions: {[string]:any}
|
||||||
---@field on_done? fun(task:LazyTask)
|
---@field on_done? fun(task:LazyTask)
|
||||||
|
@ -31,210 +25,146 @@ local Task = setmetatable({}, { __index = Async.Async })
|
||||||
---@param plugin LazyPlugin
|
---@param plugin LazyPlugin
|
||||||
---@param name string
|
---@param name string
|
||||||
---@param opts? TaskOptions
|
---@param opts? TaskOptions
|
||||||
---@param task LazyTaskFn
|
---@param task fun(task:LazyTask)
|
||||||
function Task.new(plugin, name, task, opts)
|
function Task.new(plugin, name, task, opts)
|
||||||
local self = setmetatable({}, { __index = Task })
|
local self = setmetatable({}, {
|
||||||
---@async
|
__index = Task,
|
||||||
Task.init(self, function()
|
})
|
||||||
self:_run(task)
|
|
||||||
end)
|
|
||||||
self:set_level()
|
|
||||||
self._opts = opts or {}
|
self._opts = opts or {}
|
||||||
self._log = {}
|
self._running = {}
|
||||||
|
self._task = task
|
||||||
|
self._started = nil
|
||||||
self.plugin = plugin
|
self.plugin = plugin
|
||||||
self.name = name
|
self.name = name
|
||||||
self._started = vim.uv.hrtime()
|
self.output = ""
|
||||||
|
self.status = ""
|
||||||
|
plugin._.tasks = plugin._.tasks or {}
|
||||||
---@param other LazyTask
|
---@param other LazyTask
|
||||||
plugin._.tasks = vim.tbl_filter(function(other)
|
plugin._.tasks = vim.tbl_filter(function(other)
|
||||||
return other.name ~= name or other:running()
|
return other.name ~= name or other:is_running()
|
||||||
end, plugin._.tasks or {})
|
end, plugin._.tasks)
|
||||||
table.insert(plugin._.tasks, self)
|
table.insert(plugin._.tasks, self)
|
||||||
self:render()
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param level? number
|
function Task:has_started()
|
||||||
---@return LazyMsg[]
|
return self._started ~= nil
|
||||||
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
|
end
|
||||||
|
|
||||||
---@param level? number
|
function Task:is_done()
|
||||||
function Task:output(level)
|
return self:has_started() and not self:is_running()
|
||||||
return table.concat(
|
|
||||||
---@param m LazyMsg
|
|
||||||
vim.tbl_map(function(m)
|
|
||||||
return m.msg
|
|
||||||
end, self:get_log(level)),
|
|
||||||
"\n"
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Task:status()
|
function Task:is_running()
|
||||||
local ret = self._log[#self._log]
|
return self:has_started() and self._ended == nil
|
||||||
local msg = ret and vim.trim(ret.msg) or ""
|
|
||||||
return msg ~= "" and msg or nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Task:has_errors()
|
function Task:start()
|
||||||
return self._level >= vim.log.levels.ERROR
|
if vim.in_fast_event() then
|
||||||
end
|
return vim.schedule(function()
|
||||||
|
self:start()
|
||||||
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)
|
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
|
end
|
||||||
level = level or vim.log.levels.DEBUG
|
self._started = vim.uv.hrtime()
|
||||||
self._level = math.max(self._level or 0, level or 0)
|
---@type boolean, string|any
|
||||||
msg = type(msg) == "table" and table.concat(msg, "\n") or msg
|
local ok, err = pcall(self._task, self, self._opts)
|
||||||
---@cast msg string
|
if not ok then
|
||||||
table.insert(self._log, { msg = msg, level = level })
|
self.error = err or "failed"
|
||||||
self:render()
|
|
||||||
if Config.headless() then
|
|
||||||
self:headless()
|
|
||||||
end
|
end
|
||||||
end
|
self:_check()
|
||||||
|
|
||||||
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
|
end
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
function Task:_done()
|
function Task:_check()
|
||||||
if Config.headless() and Config.options.headless.task then
|
for _, state in ipairs(self._running) do
|
||||||
local ms = math.floor(self:time() + 0.5)
|
if state() then
|
||||||
self:log("Finished task " .. self.name .. " in " .. ms .. "ms", vim.log.levels.INFO)
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
self._ended = vim.uv.hrtime()
|
self._ended = vim.uv.hrtime()
|
||||||
if self._opts.on_done then
|
if self._opts.on_done then
|
||||||
self._opts.on_done(self)
|
self._opts.on_done(self)
|
||||||
end
|
end
|
||||||
self:render()
|
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
|
||||||
vim.schedule(function()
|
|
||||||
vim.api.nvim_exec_autocmds("User", {
|
vim.api.nvim_exec_autocmds("User", {
|
||||||
pattern = "LazyPlugin" .. self.name:sub(1, 1):upper() .. self.name:sub(2),
|
pattern = "LazyPlugin" .. self.name:sub(1, 1):upper() .. self.name:sub(2),
|
||||||
data = { plugin = self.plugin.name },
|
data = { plugin = self.plugin.name },
|
||||||
})
|
})
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Task:time()
|
function Task:time()
|
||||||
return ((self._ended or vim.uv.hrtime()) - self._started) / 1e6
|
if not self:has_started() then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
if not self:is_done() then
|
||||||
|
return (vim.uv.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)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@async
|
|
||||||
---@param cmd string
|
---@param cmd string
|
||||||
---@param opts? ProcessOpts
|
---@param opts? ProcessOpts
|
||||||
function Task:spawn(cmd, opts)
|
function Task:spawn(cmd, opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
local on_line = opts.on_line
|
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)
|
function opts.on_line(line)
|
||||||
if not headless then
|
self.status = line
|
||||||
return self:log(line, vim.log.levels.TRACE)
|
|
||||||
end
|
|
||||||
if on_line then
|
if on_line then
|
||||||
pcall(on_line, line)
|
pcall(on_line, line)
|
||||||
end
|
end
|
||||||
|
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
|
||||||
end
|
end
|
||||||
|
|
||||||
if headless then
|
---@param output string
|
||||||
opts.on_data = function(data)
|
function opts.on_exit(ok, output)
|
||||||
-- prefix with plugin name
|
self.output = self.output .. output
|
||||||
io.write(Terminal.prefix(data, self:prefix()))
|
if not ok then
|
||||||
|
self.error = self.error and (self.error .. "\n" .. output) or output
|
||||||
end
|
end
|
||||||
|
if on_exit then
|
||||||
|
pcall(on_exit, ok, output)
|
||||||
|
end
|
||||||
|
self:_check()
|
||||||
end
|
end
|
||||||
|
|
||||||
local proc = Process.spawn(cmd, opts)
|
local proc = Process.spawn(cmd, opts)
|
||||||
proc:wait()
|
table.insert(self._running, function()
|
||||||
|
return proc and not proc:is_closing()
|
||||||
local ok = proc.code == 0 and proc.signal == 0
|
end)
|
||||||
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
|
|
||||||
|
|
||||||
if opts.on_exit then
|
|
||||||
pcall(opts.on_exit, ok, proc.data)
|
|
||||||
end
|
|
||||||
return ok
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Task:prefix()
|
---@param tasks (LazyTask?)[]
|
||||||
local plugin = "[" .. self.plugin.name .. "] "
|
function Task.all_done(tasks)
|
||||||
local task = string.rep(" ", 20 - #(self.name .. self.plugin.name)) .. self.name
|
for _, task in ipairs(tasks) do
|
||||||
|
if task and not task:is_done() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
return colors and Terminal.magenta(plugin) .. Terminal.cyan(task) .. Terminal.bright_black(" | ")
|
function Task:wait()
|
||||||
or plugin .. " " .. task .. " | "
|
while self:is_running() do
|
||||||
|
vim.wait(10)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return Task
|
return Task
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
local Config = require("lazy.core.config")
|
||||||
local Loader = require("lazy.core.loader")
|
local Loader = require("lazy.core.loader")
|
||||||
local Rocks = require("lazy.pkg.rockspec")
|
|
||||||
local Util = require("lazy.util")
|
local Util = require("lazy.util")
|
||||||
|
|
||||||
---@type table<string, LazyTaskDef>
|
---@type table<string, LazyTaskDef>
|
||||||
|
@ -8,49 +8,26 @@ local M = {}
|
||||||
---@param plugin LazyPlugin
|
---@param plugin LazyPlugin
|
||||||
local function get_build_file(plugin)
|
local function get_build_file(plugin)
|
||||||
for _, path in ipairs({ "build.lua", "build/init.lua" }) do
|
for _, path in ipairs({ "build.lua", "build/init.lua" }) do
|
||||||
if Util.file_exists(plugin.dir .. "/" .. path) then
|
path = plugin.dir .. "/" .. path
|
||||||
|
if Util.file_exists(path) then
|
||||||
return path
|
return path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
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 = {
|
M.build = {
|
||||||
---@param opts? {force:boolean}
|
---@param opts? {force:boolean}
|
||||||
skip = function(plugin, opts)
|
skip = function(plugin, opts)
|
||||||
if opts and opts.force then
|
if opts and opts.force then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return not ((plugin._.dirty or plugin._.build) and (plugin.build or get_build_file(plugin)))
|
return not (plugin._.dirty and (plugin.build or get_build_file(plugin)))
|
||||||
end,
|
end,
|
||||||
---@async
|
|
||||||
run = function(self)
|
run = function(self)
|
||||||
vim.cmd([[silent! runtime plugin/rplugin.vim]])
|
vim.cmd([[silent! runtime plugin/rplugin.vim]])
|
||||||
|
|
||||||
|
Loader.load(self.plugin, { task = "build" })
|
||||||
|
|
||||||
local builders = self.plugin.build
|
local builders = self.plugin.build
|
||||||
|
|
||||||
-- Skip if `build` is set to `false`
|
-- Skip if `build` is set to `false`
|
||||||
|
@ -58,27 +35,39 @@ M.build = {
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
builders = builders or get_build_file(self.plugin)
|
local build_file = get_build_file(self.plugin)
|
||||||
|
if build_file then
|
||||||
|
if builders then
|
||||||
|
if Config.options.build.warn_on_override then
|
||||||
|
Util.warn(
|
||||||
|
("Plugin **%s** provides its own build script, but you also defined a `build` command.\nThe `build.lua` file will not be used"):format(
|
||||||
|
self.plugin.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
builders = function()
|
||||||
|
Loader.source(build_file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
if builders then
|
if builders then
|
||||||
builders = type(builders) == "table" and builders or { builders }
|
builders = type(builders) == "table" and builders or { builders }
|
||||||
---@cast builders (string|fun(LazyPlugin))[]
|
---@cast builders (string|fun(LazyPlugin))[]
|
||||||
for _, build in ipairs(builders) do
|
for _, build in ipairs(builders) do
|
||||||
if type(build) == "function" then
|
if type(build) == "string" and build:sub(1, 1) == ":" then
|
||||||
|
local cmd = vim.api.nvim_parse_cmd(build:sub(2), {})
|
||||||
|
self.output = vim.api.nvim_cmd(cmd, { output = true })
|
||||||
|
elseif type(build) == "function" then
|
||||||
build(self.plugin)
|
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
|
else
|
||||||
B.shell(self, build)
|
local shell = vim.env.SHELL or vim.o.shell
|
||||||
|
local shell_args = shell:find("cmd.exe", 1, true) and "/c" or "-c"
|
||||||
|
|
||||||
|
self:spawn(shell, {
|
||||||
|
args = { shell_args, build },
|
||||||
|
cwd = self.plugin.dir,
|
||||||
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -87,23 +76,12 @@ M.build = {
|
||||||
|
|
||||||
M.docs = {
|
M.docs = {
|
||||||
skip = function(plugin)
|
skip = function(plugin)
|
||||||
return not plugin._.is_local and not plugin._.dirty
|
return not plugin._.dirty
|
||||||
end,
|
end,
|
||||||
run = function(self)
|
run = function(self)
|
||||||
local docs = self.plugin.dir .. "/doc"
|
local docs = self.plugin.dir .. "/doc/"
|
||||||
if Util.file_exists(docs) then
|
if Util.file_exists(docs) then
|
||||||
self:log(vim.api.nvim_cmd({ cmd = "helptags", args = { docs } }, { output = true }))
|
self.output = 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
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,214 +0,0 @@
|
||||||
---@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
|
|
|
@ -1,137 +0,0 @@
|
||||||
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,
|
|
||||||
})
|
|
|
@ -1,29 +0,0 @@
|
||||||
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
|
|
|
@ -1,54 +0,0 @@
|
||||||
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
|
|
|
@ -1,343 +0,0 @@
|
||||||
--# 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
|
|
|
@ -6,7 +6,7 @@ local M = {}
|
||||||
M._stats = {
|
M._stats = {
|
||||||
-- startuptime in milliseconds till UIEnter
|
-- startuptime in milliseconds till UIEnter
|
||||||
startuptime = 0,
|
startuptime = 0,
|
||||||
-- when true, startuptime is the accurate cputime for the Neovim process. (Linux & macOS)
|
-- 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
|
-- 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.
|
-- when false, startuptime is calculated based on a delta with a timestamp when lazy started.
|
||||||
real_cputime = false,
|
real_cputime = false,
|
||||||
|
@ -21,7 +21,6 @@ M.C = nil
|
||||||
|
|
||||||
function M.on_ui_enter()
|
function M.on_ui_enter()
|
||||||
M._stats.startuptime = M.track("UIEnter")
|
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 })
|
vim.api.nvim_exec_autocmds("User", { pattern = "LazyVimStarted", modeline = false })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
---@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
|
|
|
@ -2,28 +2,28 @@
|
||||||
---@alias LazyPluginKind "normal"|"clean"|"disabled"
|
---@alias LazyPluginKind "normal"|"clean"|"disabled"
|
||||||
|
|
||||||
---@class LazyPluginState
|
---@class LazyPluginState
|
||||||
---@field cache? table<string,any>
|
---@field fid number id of the plugin spec fragment
|
||||||
---@field cloned? boolean
|
---@field fpid? number parent id of the plugin spec fragment
|
||||||
---@field cond? boolean
|
---@field fdeps? number[] children ids of the fragment
|
||||||
---@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 loaded? {[string]:string}|{time:number}
|
||||||
---@field outdated? boolean
|
---@field installed? boolean
|
||||||
---@field rtp_loaded? boolean
|
|
||||||
---@field tasks? LazyTask[]
|
---@field tasks? LazyTask[]
|
||||||
---@field updated? {from:string, to:string}
|
|
||||||
---@field updates? {from:GitInfo, to:GitInfo}
|
|
||||||
---@field last_check? number
|
|
||||||
---@field working? boolean
|
---@field working? boolean
|
||||||
---@field pkg? LazyPkg
|
---@field dirty? boolean
|
||||||
|
---@field updated? {from:string, to:string}
|
||||||
|
---@field is_local? boolean
|
||||||
|
---@field updates? {from:GitInfo, to:GitInfo}
|
||||||
|
---@field cloned? boolean
|
||||||
|
---@field outdated? boolean
|
||||||
|
---@field kind? LazyPluginKind
|
||||||
|
---@field dep? boolean True if this plugin is only in the spec as a dependency
|
||||||
|
---@field cond? boolean
|
||||||
|
---@field super? LazyPlugin
|
||||||
|
---@field module? string
|
||||||
|
---@field dir? string Explicit dir or dev set for this plugin
|
||||||
|
---@field rtp_loaded? boolean
|
||||||
|
---@field handlers? LazyPluginHandlers
|
||||||
|
---@field cache? table<string,any>
|
||||||
|
|
||||||
---@alias PluginOpts table|fun(self:LazyPlugin, opts:table):table?
|
---@alias PluginOpts table|fun(self:LazyPlugin, opts:table):table?
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
---@field init? fun(self:LazyPlugin) Will always be run
|
---@field init? fun(self:LazyPlugin) Will always be run
|
||||||
---@field deactivate? fun(self:LazyPlugin) Unload/Stop a plugin
|
---@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 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 build? string|fun(self:LazyPlugin)|(string|fun(self:LazyPlugin))[]
|
||||||
---@field opts? PluginOpts
|
---@field opts? PluginOpts
|
||||||
|
|
||||||
---@class LazyPluginHandlers
|
---@class LazyPluginHandlers
|
||||||
|
@ -60,12 +60,9 @@
|
||||||
---@field lazy? boolean
|
---@field lazy? boolean
|
||||||
---@field priority? number Only useful for lazy=false plugins to force loading certain plugins first. Default priority is 50
|
---@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 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
|
---@class LazyPlugin: LazyPluginBase,LazyPluginHandlers,LazyPluginHooks,LazyPluginRef
|
||||||
---@field dependencies? string[]
|
---@field dependencies? string[]
|
||||||
---@field specs? string|string[]|LazyPluginSpec[]
|
|
||||||
---@field _ LazyPluginState
|
---@field _ LazyPluginState
|
||||||
|
|
||||||
---@class LazyPluginSpecHandlers
|
---@class LazyPluginSpecHandlers
|
||||||
|
@ -76,27 +73,11 @@
|
||||||
---@field module? false
|
---@field module? false
|
||||||
|
|
||||||
---@class LazyPluginSpec: LazyPluginBase,LazyPluginSpecHandlers,LazyPluginHooks,LazyPluginRef
|
---@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 dependencies? string|string[]|LazyPluginSpec[]
|
||||||
---@field specs? string|string[]|LazyPluginSpec[]
|
|
||||||
|
|
||||||
---@alias LazySpec string|LazyPluginSpec|LazySpecImport|LazySpec[]
|
---@alias LazySpec string|LazyPluginSpec|LazySpecImport|LazySpec[]
|
||||||
|
|
||||||
---@class LazySpecImport
|
---@class LazySpecImport
|
||||||
---@field import string|(fun():LazyPluginSpec) spec module to import
|
---@field import string spec module to import
|
||||||
---@field name? string
|
|
||||||
---@field enabled? boolean|(fun():boolean)
|
---@field enabled? boolean|(fun():boolean)
|
||||||
---@field cond? 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
|
|
||||||
|
|
|
@ -73,24 +73,28 @@ end
|
||||||
---@param fn F
|
---@param fn F
|
||||||
---@return F
|
---@return F
|
||||||
function M.throttle(ms, fn)
|
function M.throttle(ms, fn)
|
||||||
---@type Async
|
local timer = vim.uv.new_timer()
|
||||||
local async
|
local running = false
|
||||||
local pending = false
|
local first = true
|
||||||
|
|
||||||
return function()
|
return function(...)
|
||||||
if async and async:running() then
|
local args = { ... }
|
||||||
pending = true
|
local wrapped = function()
|
||||||
return
|
fn(unpack(args))
|
||||||
|
end
|
||||||
|
if not running then
|
||||||
|
if first then
|
||||||
|
wrapped()
|
||||||
|
first = false
|
||||||
end
|
end
|
||||||
---@async
|
|
||||||
async = require("lazy.async").new(function()
|
|
||||||
repeat
|
|
||||||
pending = false
|
|
||||||
fn()
|
|
||||||
async:sleep(ms)
|
|
||||||
|
|
||||||
until not pending
|
timer:start(ms, 0, function()
|
||||||
|
running = false
|
||||||
|
vim.schedule(wrapped)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
running = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -162,21 +166,12 @@ end
|
||||||
---@param opts? LazyCmdOptions|{filetype?:string}
|
---@param opts? LazyCmdOptions|{filetype?:string}
|
||||||
function M.float_cmd(cmd, opts)
|
function M.float_cmd(cmd, opts)
|
||||||
opts = opts or {}
|
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)
|
local float = M.float(opts)
|
||||||
if opts.filetype then
|
if opts.filetype then
|
||||||
vim.bo[float.buf].filetype = opts.filetype
|
vim.bo[float.buf].filetype = opts.filetype
|
||||||
end
|
end
|
||||||
|
local Process = require("lazy.manage.process")
|
||||||
|
local lines = Process.exec(cmd, { cwd = opts.cwd })
|
||||||
vim.api.nvim_buf_set_lines(float.buf, 0, -1, false, lines)
|
vim.api.nvim_buf_set_lines(float.buf, 0, -1, false, lines)
|
||||||
vim.bo[float.buf].modifiable = false
|
vim.bo[float.buf].modifiable = false
|
||||||
return float
|
return float
|
||||||
|
@ -242,25 +237,20 @@ function M._dump(value, result)
|
||||||
table.insert(result, tostring(value))
|
table.insert(result, tostring(value))
|
||||||
elseif t == "string" then
|
elseif t == "string" then
|
||||||
table.insert(result, ("%q"):format(value))
|
table.insert(result, ("%q"):format(value))
|
||||||
elseif t == "table" and value._raw then
|
|
||||||
table.insert(result, value._raw)
|
|
||||||
elseif t == "table" then
|
elseif t == "table" then
|
||||||
table.insert(result, "{")
|
table.insert(result, "{")
|
||||||
for _, v in ipairs(value) do
|
local i = 1
|
||||||
M._dump(v, result)
|
|
||||||
table.insert(result, ",")
|
|
||||||
end
|
|
||||||
---@diagnostic disable-next-line: no-unknown
|
---@diagnostic disable-next-line: no-unknown
|
||||||
for k, v in pairs(value) do
|
for k, v in pairs(value) do
|
||||||
if type(k) == "string" then
|
if k == i then
|
||||||
if k:match("^[a-zA-Z]+$") then
|
elseif type(k) == "string" then
|
||||||
table.insert(result, ("%s="):format(k))
|
|
||||||
else
|
|
||||||
table.insert(result, ("[%q]="):format(k))
|
table.insert(result, ("[%q]="):format(k))
|
||||||
|
else
|
||||||
|
table.insert(result, k .. "=")
|
||||||
end
|
end
|
||||||
M._dump(v, result)
|
M._dump(v, result)
|
||||||
table.insert(result, ",")
|
table.insert(result, ",")
|
||||||
end
|
i = i + 1
|
||||||
end
|
end
|
||||||
table.insert(result, "}")
|
table.insert(result, "}")
|
||||||
else
|
else
|
||||||
|
|
|
@ -30,22 +30,19 @@ M.colors = {
|
||||||
Button = "CursorLine",
|
Button = "CursorLine",
|
||||||
ButtonActive = "Visual",
|
ButtonActive = "Visual",
|
||||||
TaskOutput = "MsgArea", -- task output
|
TaskOutput = "MsgArea", -- task output
|
||||||
Error = "DiagnosticError", -- task errors
|
TaskError = "ErrorMsg", -- task errors
|
||||||
Warning = "DiagnosticWarn", -- task errors
|
|
||||||
Info = "DiagnosticInfo", -- task errors
|
|
||||||
Dir = "@markup.link", -- directory
|
Dir = "@markup.link", -- directory
|
||||||
Url = "@markup.link", -- url
|
Url = "@markup.link", -- url
|
||||||
Bold = { bold = true },
|
|
||||||
Italic = { italic = true },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
M.did_setup = false
|
M.did_setup = false
|
||||||
|
|
||||||
function M.set_hl()
|
function M.set_hl()
|
||||||
for hl_group, link in pairs(M.colors) do
|
for hl_group, link in pairs(M.colors) do
|
||||||
local hl = type(link) == "table" and link or { link = link }
|
vim.api.nvim_set_hl(0, "Lazy" .. hl_group, {
|
||||||
hl.default = true
|
link = link,
|
||||||
vim.api.nvim_set_hl(0, "Lazy" .. hl_group, hl)
|
default = true,
|
||||||
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -57,11 +54,6 @@ function M.setup()
|
||||||
M.did_setup = true
|
M.did_setup = true
|
||||||
|
|
||||||
M.set_hl()
|
M.set_hl()
|
||||||
vim.api.nvim_create_autocmd("VimEnter", {
|
|
||||||
callback = function()
|
|
||||||
M.set_hl()
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
vim.api.nvim_create_autocmd("ColorScheme", {
|
vim.api.nvim_create_autocmd("ColorScheme", {
|
||||||
callback = function()
|
callback = function()
|
||||||
M.set_hl()
|
M.set_hl()
|
||||||
|
|
|
@ -34,21 +34,6 @@ M.commands = {
|
||||||
health = function()
|
health = function()
|
||||||
vim.cmd.checkhealth("lazy")
|
vim.cmd.checkhealth("lazy")
|
||||||
end,
|
end,
|
||||||
---@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()
|
home = function()
|
||||||
View.show("home")
|
View.show("home")
|
||||||
end,
|
end,
|
||||||
|
@ -89,7 +74,7 @@ M.commands = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function M.complete(cmd, prefix)
|
function M.complete(cmd, prefix)
|
||||||
if not (ViewConfig.commands[cmd] or {}).plugins and cmd ~= "pkg" then
|
if not (ViewConfig.commands[cmd] or {}).plugins then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
---@type string[]
|
---@type string[]
|
||||||
|
@ -146,7 +131,7 @@ end
|
||||||
---@return string, string[]
|
---@return string, string[]
|
||||||
function M.parse(args)
|
function M.parse(args)
|
||||||
local parts = vim.split(vim.trim(args), "%s+")
|
local parts = vim.split(vim.trim(args), "%s+")
|
||||||
if vim.startswith("Lazy", parts[1]) then
|
if parts[1]:find("Lazy") then
|
||||||
table.remove(parts, 1)
|
table.remove(parts, 1)
|
||||||
end
|
end
|
||||||
if args:sub(-1) == " " then
|
if args:sub(-1) == " " then
|
||||||
|
|
|
@ -34,8 +34,6 @@ M.keys = {
|
||||||
profile_sort = "<C-s>",
|
profile_sort = "<C-s>",
|
||||||
profile_filter = "<C-f>",
|
profile_filter = "<C-f>",
|
||||||
abort = "<C-c>",
|
abort = "<C-c>",
|
||||||
next = "]]",
|
|
||||||
prev = "[[",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
---@type table<string,LazyViewCommand>
|
---@type table<string,LazyViewCommand>
|
||||||
|
|
|
@ -166,7 +166,7 @@ function M:mount()
|
||||||
self:augroup(true)
|
self:augroup(true)
|
||||||
end, { win = true })
|
end, { win = true })
|
||||||
self:focus()
|
self:focus()
|
||||||
self:on_key(ViewConfig.keys.close, self.close, "Close")
|
self:on_key(ViewConfig.keys.close, self.close)
|
||||||
self:on({ "BufDelete", "BufHidden" }, self.close)
|
self:on({ "BufDelete", "BufHidden" }, self.close)
|
||||||
|
|
||||||
if vim.bo[self.buf].buftype == "" then
|
if vim.bo[self.buf].buftype == "" then
|
||||||
|
@ -252,7 +252,7 @@ end
|
||||||
---@param fn fun(self?)
|
---@param fn fun(self?)
|
||||||
---@param desc? string
|
---@param desc? string
|
||||||
---@param mode? string[]
|
---@param mode? string[]
|
||||||
function M:on_key(key, fn, desc, mode)
|
function M:on_key(key, fn, desc,mode)
|
||||||
vim.keymap.set(mode or "n", key, function()
|
vim.keymap.set(mode or "n", key, function()
|
||||||
fn(self)
|
fn(self)
|
||||||
end, {
|
end, {
|
||||||
|
@ -295,7 +295,6 @@ function M:close(opts)
|
||||||
vim.diagnostic.reset(Config.ns, buf)
|
vim.diagnostic.reset(Config.ns, buf)
|
||||||
vim.api.nvim_buf_delete(buf, { force = true })
|
vim.api.nvim_buf_delete(buf, { force = true })
|
||||||
end
|
end
|
||||||
vim.cmd.redraw()
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -67,10 +67,7 @@ function M.create()
|
||||||
self.state = vim.deepcopy(default_state)
|
self.state = vim.deepcopy(default_state)
|
||||||
|
|
||||||
self.render = Render.new(self)
|
self.render = Render.new(self)
|
||||||
local update = self.update
|
self.update = Util.throttle(Config.options.ui.throttle, self.update)
|
||||||
self.update = Util.throttle(Config.options.ui.throttle, function()
|
|
||||||
update(self)
|
|
||||||
end)
|
|
||||||
|
|
||||||
for _, pattern in ipairs({ "LazyRender", "LazyFloatResized" }) do
|
for _, pattern in ipairs({ "LazyRender", "LazyFloatResized" }) do
|
||||||
self:on({ "User" }, function()
|
self:on({ "User" }, function()
|
||||||
|
@ -83,11 +80,8 @@ function M.create()
|
||||||
|
|
||||||
vim.keymap.set("n", ViewConfig.keys.abort, function()
|
vim.keymap.set("n", ViewConfig.keys.abort, function()
|
||||||
require("lazy.manage.process").abort()
|
require("lazy.manage.process").abort()
|
||||||
require("lazy.async").abort()
|
|
||||||
return ViewConfig.keys.abort
|
return ViewConfig.keys.abort
|
||||||
end, { silent = true, buffer = self.buf, expr = true, desc = "Abort" })
|
end, { silent = true, buffer = self.buf, expr = true })
|
||||||
|
|
||||||
vim.keymap.set("n", "gx", "K", { buffer = self.buf, remap = true })
|
|
||||||
|
|
||||||
-- plugin details
|
-- plugin details
|
||||||
self:on_key(ViewConfig.keys.details, function()
|
self:on_key(ViewConfig.keys.details, function()
|
||||||
|
@ -97,49 +91,17 @@ function M.create()
|
||||||
name = plugin.name,
|
name = plugin.name,
|
||||||
kind = plugin._.kind,
|
kind = plugin._.kind,
|
||||||
}
|
}
|
||||||
|
self.state.plugin = not vim.deep_equal(self.state.plugin, selected) and selected or nil
|
||||||
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()
|
self:update()
|
||||||
end
|
end
|
||||||
end, "Details")
|
end)
|
||||||
|
|
||||||
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()
|
self:on_key(ViewConfig.keys.profile_sort, function()
|
||||||
if self.state.mode == "profile" then
|
if self.state.mode == "profile" then
|
||||||
self.state.profile.sort_time_taken = not self.state.profile.sort_time_taken
|
self.state.profile.sort_time_taken = not self.state.profile.sort_time_taken
|
||||||
self:update()
|
self:update()
|
||||||
end
|
end
|
||||||
end, "Sort Profile")
|
end)
|
||||||
|
|
||||||
self:on_key(ViewConfig.keys.profile_filter, function()
|
self:on_key(ViewConfig.keys.profile_filter, function()
|
||||||
if self.state.mode == "profile" then
|
if self.state.mode == "profile" then
|
||||||
|
@ -159,18 +121,17 @@ function M.create()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end, "Filter Profile")
|
end)
|
||||||
|
|
||||||
for lhs, rhs in pairs(Config.options.ui.custom_keys) do
|
for lhs, rhs in pairs(Config.options.ui.custom_keys) do
|
||||||
if rhs then
|
if rhs then
|
||||||
local handler = type(rhs) == "table" and rhs[1] or rhs
|
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()
|
self:on_key(lhs, function()
|
||||||
local plugin = self.render:get_plugin()
|
local plugin = self.render:get_plugin()
|
||||||
if plugin then
|
if plugin then
|
||||||
handler(plugin)
|
handler(plugin)
|
||||||
end
|
end
|
||||||
end, desc)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -181,7 +142,9 @@ end
|
||||||
|
|
||||||
function M:update()
|
function M:update()
|
||||||
if self.buf and vim.api.nvim_buf_is_valid(self.buf) then
|
if self.buf and vim.api.nvim_buf_is_valid(self.buf) then
|
||||||
|
vim.bo[self.buf].modifiable = true
|
||||||
self.render:update()
|
self.render:update()
|
||||||
|
vim.bo[self.buf].modifiable = false
|
||||||
vim.cmd.redraw()
|
vim.cmd.redraw()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -220,17 +183,17 @@ function M:setup_patterns()
|
||||||
["(https?://%S+)"] = function(url)
|
["(https?://%S+)"] = function(url)
|
||||||
Util.open(url)
|
Util.open(url)
|
||||||
end,
|
end,
|
||||||
}, self.hover, "Hover")
|
}, self.hover)
|
||||||
self:on_pattern(ViewConfig.keys.diff, {
|
self:on_pattern(ViewConfig.keys.diff, {
|
||||||
[commit_pattern] = function(hash)
|
[commit_pattern] = function(hash)
|
||||||
self:diff({ commit = hash })
|
self:diff({ commit = hash })
|
||||||
end,
|
end,
|
||||||
}, self.diff, "Diff")
|
}, self.diff)
|
||||||
self:on_pattern(ViewConfig.commands.restore.key_plugin, {
|
self:on_pattern(ViewConfig.commands.restore.key_plugin, {
|
||||||
[commit_pattern] = function(hash)
|
[commit_pattern] = function(hash)
|
||||||
self:restore({ commit = hash })
|
self:restore({ commit = hash })
|
||||||
end,
|
end,
|
||||||
}, self.restore, "Restore")
|
}, self.restore)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param opts? {commit:string}
|
---@param opts? {commit:string}
|
||||||
|
@ -295,8 +258,7 @@ end
|
||||||
---@param key string
|
---@param key string
|
||||||
---@param patterns table<string, fun(str:string)>
|
---@param patterns table<string, fun(str:string)>
|
||||||
---@param fallback? fun(self)
|
---@param fallback? fun(self)
|
||||||
---@param desc? string
|
function M:on_pattern(key, patterns, fallback)
|
||||||
function M:on_pattern(key, patterns, fallback, desc)
|
|
||||||
self:on_key(key, function()
|
self:on_key(key, function()
|
||||||
local line = vim.api.nvim_get_current_line()
|
local line = vim.api.nvim_get_current_line()
|
||||||
local pos = vim.api.nvim_win_get_cursor(0)
|
local pos = vim.api.nvim_win_get_cursor(0)
|
||||||
|
@ -318,7 +280,7 @@ function M:on_pattern(key, patterns, fallback, desc)
|
||||||
if fallback then
|
if fallback then
|
||||||
fallback(self)
|
fallback(self)
|
||||||
end
|
end
|
||||||
end, desc)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function M:setup_modes()
|
function M:setup_modes()
|
||||||
|
@ -344,12 +306,8 @@ function M:setup_modes()
|
||||||
f, t = t, f
|
f, t = t, f
|
||||||
end
|
end
|
||||||
for i = f, t do
|
for i = f, t do
|
||||||
local plugin = self.render:get_plugin(i)
|
plugins[#plugins + 1] = self.render:get_plugin(i)
|
||||||
if plugin then
|
|
||||||
plugins[plugin.name] = plugin
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
plugins = vim.tbl_values(plugins)
|
|
||||||
else
|
else
|
||||||
plugins[1] = self.render:get_plugin()
|
plugins[1] = self.render:get_plugin()
|
||||||
end
|
end
|
||||||
|
|
|
@ -51,7 +51,7 @@ function M:update()
|
||||||
if plugin._.tasks then
|
if plugin._.tasks then
|
||||||
for _, task in ipairs(plugin._.tasks) do
|
for _, task in ipairs(plugin._.tasks) do
|
||||||
self.progress.total = self.progress.total + 1
|
self.progress.total = self.progress.total + 1
|
||||||
if not task:running() then
|
if not task:is_running() then
|
||||||
self.progress.done = self.progress.done + 1
|
self.progress.done = self.progress.done + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -74,17 +74,7 @@ function M:update()
|
||||||
end
|
end
|
||||||
|
|
||||||
self:trim()
|
self:trim()
|
||||||
|
|
||||||
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)
|
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(
|
vim.diagnostic.set(
|
||||||
Config.ns,
|
Config.ns,
|
||||||
self.view.buf,
|
self.view.buf,
|
||||||
|
@ -94,7 +84,7 @@ function M:update()
|
||||||
diag.lnum = diag.row - 1
|
diag.lnum = diag.row - 1
|
||||||
return diag
|
return diag
|
||||||
end, self._diagnostics),
|
end, self._diagnostics),
|
||||||
{ signs = false, virtual_text = true, underline = false, virtual_lines = false }
|
{ signs = false, virtual_text = true, underline = false }
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -122,15 +112,6 @@ function M:get_plugin(row)
|
||||||
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()
|
function M:title()
|
||||||
self:nl()
|
self:nl()
|
||||||
local modes = vim.tbl_filter(function(c)
|
local modes = vim.tbl_filter(function(c)
|
||||||
|
@ -144,6 +125,8 @@ function M:title()
|
||||||
if mode.name == "home" then
|
if mode.name == "home" then
|
||||||
if self.view.state.mode == "home" then
|
if self.view.state.mode == "home" then
|
||||||
title = " lazy.nvim " .. Config.options.ui.icons.lazy
|
title = " lazy.nvim " .. Config.options.ui.icons.lazy
|
||||||
|
else
|
||||||
|
title = " lazy.nvim (H) "
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -199,15 +182,7 @@ function M:help()
|
||||||
:nl()
|
:nl()
|
||||||
self:append("or the plugin was just updated. Otherwise the plugin webpage will open."):nl():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("<d>", "LazySpecial"):append(" on a commit or plugin to open the diff view"):nl()
|
||||||
self
|
|
||||||
:append("Use ")
|
|
||||||
:append("<]]>", "LazySpecial")
|
|
||||||
:append(" and ")
|
|
||||||
:append("<[[>", "LazySpecial")
|
|
||||||
:append(" to navigate between plugins")
|
|
||||||
:nl()
|
|
||||||
:nl()
|
|
||||||
self:nl()
|
self:nl()
|
||||||
|
|
||||||
self:append("Keyboard Shortcuts", "LazyH2"):nl()
|
self:append("Keyboard Shortcuts", "LazyH2"):nl()
|
||||||
|
@ -379,37 +354,7 @@ end
|
||||||
|
|
||||||
---@param plugin LazyPlugin
|
---@param plugin LazyPlugin
|
||||||
function M:diagnostics(plugin)
|
function M:diagnostics(plugin)
|
||||||
local skip = false
|
if plugin._.updated then
|
||||||
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
|
if plugin._.updated.from == plugin._.updated.to then
|
||||||
self:diagnostic({
|
self:diagnostic({
|
||||||
message = "already up to date",
|
message = "already up to date",
|
||||||
|
@ -438,6 +383,19 @@ function M:diagnostics(plugin)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
for _, task in ipairs(plugin._.tasks or {}) do
|
||||||
|
if task:is_running() then
|
||||||
|
self:diagnostic({
|
||||||
|
severity = vim.diagnostic.severity.WARN,
|
||||||
|
message = task.name .. (task.status == "" and "" or (": " .. task.status)),
|
||||||
|
})
|
||||||
|
elseif task.error then
|
||||||
|
self:diagnostic({
|
||||||
|
message = task.name .. " failed",
|
||||||
|
severity = vim.diagnostic.severity.ERROR,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param plugin LazyPlugin
|
---@param plugin LazyPlugin
|
||||||
|
@ -476,22 +434,6 @@ function M:plugin(plugin)
|
||||||
{ name = plugin.name, from = plugin_start, to = self:row() - 1, kind = plugin._.kind }
|
{ name = plugin.name, from = plugin_start, to = self:row() - 1, kind = plugin._.kind }
|
||||||
end
|
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
|
---@param plugin LazyPlugin
|
||||||
function M:tasks(plugin)
|
function M:tasks(plugin)
|
||||||
for _, task in ipairs(plugin._.tasks or {}) do
|
for _, task in ipairs(plugin._.tasks or {}) do
|
||||||
|
@ -500,32 +442,25 @@ function M:tasks(plugin)
|
||||||
self:append(" " .. math.floor((task:time()) * 100) / 100 .. "ms", "Bold")
|
self:append(" " .. math.floor((task:time()) * 100) / 100 .. "ms", "Bold")
|
||||||
self:nl()
|
self:nl()
|
||||||
end
|
end
|
||||||
|
if task.error then
|
||||||
if not task:has_warnings() and task.name == "log" then
|
self:append(vim.trim(task.error), "LazyTaskError", { indent = 6 })
|
||||||
|
self:nl()
|
||||||
|
elseif task.name == "log" then
|
||||||
self:log(task)
|
self:log(task)
|
||||||
else
|
elseif self.view:is_selected(plugin) and task.output ~= "" and task.output ~= task.error then
|
||||||
local hls = {
|
self:append(vim.trim(task.output), "LazyTaskOutput", { indent = 6 })
|
||||||
[vim.log.levels.ERROR] = "LazyError",
|
self:nl()
|
||||||
[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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param task LazyTask
|
---@param task LazyTask
|
||||||
function M:log(task)
|
function M:log(task)
|
||||||
local log = vim.trim(task:output())
|
local log = vim.trim(task.output)
|
||||||
if log ~= "" then
|
if log ~= "" then
|
||||||
local lines = vim.split(log, "\n")
|
local lines = vim.split(log, "\n")
|
||||||
for _, line in ipairs(lines) do
|
for _, line in ipairs(lines) do
|
||||||
local ref, msg, time = line:match("^(%w+) (.*) (%(.*%))$")
|
local ref, msg, time = line:match("^(%w+) (.*) (%(.*%))$")
|
||||||
if msg then
|
|
||||||
if msg:find("^%S+!:") then
|
if msg:find("^%S+!:") then
|
||||||
self:diagnostic({ message = "Breaking Changes", severity = vim.diagnostic.severity.WARN })
|
self:diagnostic({ message = "Breaking Changes", severity = vim.diagnostic.severity.WARN })
|
||||||
end
|
end
|
||||||
|
@ -547,9 +482,6 @@ function M:log(task)
|
||||||
})
|
})
|
||||||
self:append(" " .. time, "LazyComment")
|
self:append(" " .. time, "LazyComment")
|
||||||
self:nl()
|
self:nl()
|
||||||
-- else
|
|
||||||
-- self:append(line, "LazyTaskOutput", { indent = 6 }):nl()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
self:nl()
|
self:nl()
|
||||||
end
|
end
|
||||||
|
@ -579,11 +511,6 @@ function M:details(plugin)
|
||||||
table.insert(props, { "commit", git.commit:sub(1, 7), "LazyCommit" })
|
table.insert(props, { "commit", git.commit:sub(1, 7), "LazyCommit" })
|
||||||
end
|
end
|
||||||
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
|
if Util.file_exists(plugin.dir .. "/README.md") then
|
||||||
table.insert(props, { "readme", "README.md" })
|
table.insert(props, { "readme", "README.md" })
|
||||||
end
|
end
|
||||||
|
@ -759,7 +686,7 @@ function M:debug()
|
||||||
---@type string[]
|
---@type string[]
|
||||||
plugins = vim.tbl_values(plugins)
|
plugins = vim.tbl_values(plugins)
|
||||||
table.sort(plugins)
|
table.sort(plugins)
|
||||||
self:append(Config.options.ui.icons.debug, "LazySpecial", { indent = 2 })
|
self:append("● ", "LazySpecial", { indent = 2 })
|
||||||
if handler_type == "keys" then
|
if handler_type == "keys" then
|
||||||
for k, v in pairs(Config.plugins[plugins[1]]._.handlers.keys) do
|
for k, v in pairs(Config.plugins[plugins[1]]._.handlers.keys) do
|
||||||
if k == value then
|
if k == value then
|
||||||
|
|
|
@ -17,7 +17,7 @@ return {
|
||||||
{
|
{
|
||||||
filter = function(plugin)
|
filter = function(plugin)
|
||||||
return has_task(plugin, function(task)
|
return has_task(plugin, function(task)
|
||||||
return task:has_errors()
|
return task.error ~= nil
|
||||||
end)
|
end)
|
||||||
end,
|
end,
|
||||||
title = "Failed",
|
title = "Failed",
|
||||||
|
@ -28,24 +28,19 @@ return {
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return has_task(plugin, function(task)
|
return has_task(plugin, function(task)
|
||||||
return task:running()
|
return task:is_running()
|
||||||
end)
|
end)
|
||||||
end,
|
end,
|
||||||
title = "Working",
|
title = "Working",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
filter = function(plugin)
|
|
||||||
return plugin._.build
|
|
||||||
end,
|
|
||||||
title = "Build",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
filter = function(plugin)
|
filter = function(plugin)
|
||||||
return has_task(plugin, function(task)
|
return has_task(plugin, function(task)
|
||||||
if task.name ~= "log" then
|
if task.name ~= "log" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
for _, line in ipairs(vim.split(task:output(), "\n")) do
|
local lines = vim.split(task.output, "\n")
|
||||||
|
for _, line in ipairs(lines) do
|
||||||
if line:find("^%w+ %S+!:") then
|
if line:find("^%w+ %S+!:") then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
@ -76,7 +71,7 @@ return {
|
||||||
{
|
{
|
||||||
filter = function(plugin)
|
filter = function(plugin)
|
||||||
return has_task(plugin, function(task)
|
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)
|
||||||
end,
|
end,
|
||||||
title = "Log",
|
title = "Log",
|
||||||
|
@ -94,7 +89,7 @@ return {
|
||||||
title = "Not Installed",
|
title = "Not Installed",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filter = function(plugin)
|
filter = function (plugin)
|
||||||
return plugin._.outdated
|
return plugin._.outdated
|
||||||
end,
|
end,
|
||||||
title = "Outdated",
|
title = "Outdated",
|
||||||
|
|
|
@ -11,7 +11,9 @@ local Util = require("lazy.util")
|
||||||
local Text = {}
|
local Text = {}
|
||||||
|
|
||||||
function Text.new()
|
function Text.new()
|
||||||
local self = setmetatable({}, { __index = Text })
|
local self = setmetatable({}, {
|
||||||
|
__index = Text,
|
||||||
|
})
|
||||||
self._lines = {}
|
self._lines = {}
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/env bash
|
|
||||||
|
|
||||||
nvim -l tests/minit.lua --minitest
|
|
|
@ -1,4 +1 @@
|
||||||
std="vim"
|
std="vim"
|
||||||
|
|
||||||
[lints]
|
|
||||||
mixed_table="allow"
|
|
||||||
|
|
39
tests/core/e2e_spec.lua
Normal file
39
tests/core/e2e_spec.lua
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
local Git = require("lazy.manage.git")
|
||||||
|
|
||||||
|
describe("lazy", function()
|
||||||
|
before_each(function()
|
||||||
|
vim.g.lazy_did_setup = false
|
||||||
|
vim.go.loadplugins = true
|
||||||
|
for modname in pairs(package.loaded) do
|
||||||
|
if modname:find("lazy") == 1 then
|
||||||
|
package.loaded[modname] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local root = ".tests/data/nvim/lazy"
|
||||||
|
|
||||||
|
it("installs plugins", function()
|
||||||
|
local Lazy = require("lazy")
|
||||||
|
local Config = require("lazy.core.config")
|
||||||
|
|
||||||
|
local neodev = false
|
||||||
|
Lazy.setup({
|
||||||
|
{
|
||||||
|
"folke/neodev.nvim",
|
||||||
|
config = function()
|
||||||
|
neodev = true
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
"folke/paint.nvim",
|
||||||
|
}, { install_missing = true, defaults = { lazy = true } })
|
||||||
|
assert(3 == vim.tbl_count(Config.plugins))
|
||||||
|
assert(vim.uv.fs_stat(root .. "/paint.nvim/README.md"))
|
||||||
|
assert(vim.uv.fs_stat(root .. "/neodev.nvim/README.md"))
|
||||||
|
assert(not neodev)
|
||||||
|
assert(Config.plugins["neodev.nvim"]._.installed)
|
||||||
|
assert(not Config.plugins["neodev.nvim"]._.is_local)
|
||||||
|
assert.equal("https://github.com/folke/neodev.nvim.git", Git.get_origin(Config.plugins["neodev.nvim"].dir))
|
||||||
|
assert.equal("https://github.com/folke/paint.nvim.git", Git.get_origin(Config.plugins["paint.nvim"].dir))
|
||||||
|
end)
|
||||||
|
end)
|
|
@ -1,10 +1,7 @@
|
||||||
local Util = require("lazy.core.util")
|
|
||||||
|
|
||||||
describe("init", function()
|
describe("init", function()
|
||||||
it("has correct environment for tests", function()
|
it("has correct environment for tests", function()
|
||||||
for _, name in ipairs({ "config", "data", "cache", "state" }) do
|
for _, path in ipairs({ "config", "data", "cache", "state" }) do
|
||||||
local path = Util.norm(vim.fn.stdpath(name) --[[@as string]])
|
assert(vim.fn.stdpath(path):find(".tests/" .. path))
|
||||||
assert(path:find(".tests/" .. name, 1, true), path .. " not in .tests")
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -2,32 +2,23 @@ local Config = require("lazy.core.config")
|
||||||
local Handler = require("lazy.core.handler")
|
local Handler = require("lazy.core.handler")
|
||||||
local Plugin = require("lazy.core.plugin")
|
local Plugin = require("lazy.core.plugin")
|
||||||
|
|
||||||
local function inspect(obj)
|
local assert = require("luassert")
|
||||||
return vim.inspect(obj):gsub("%s+", " ")
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param plugin LazyPlugin
|
Config.setup()
|
||||||
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
|
|
||||||
|
|
||||||
---@param plugins LazyPlugin[]
|
---@param plugins LazyPlugin[]|LazyPlugin
|
||||||
local function clean(plugins)
|
local function clean(plugins)
|
||||||
return vim.tbl_map(function(plugin)
|
local p = plugins
|
||||||
plugin = resolve(plugin)
|
plugins = type(plugins) == "table" and plugins or { plugins }
|
||||||
plugin[1] = nil
|
for _, plugin in pairs(plugins) do
|
||||||
plugin._.frags = nil
|
plugin._.fid = nil
|
||||||
|
plugin._.fpid = nil
|
||||||
|
plugin._.fdeps = nil
|
||||||
if plugin._.dep == false then
|
if plugin._.dep == false then
|
||||||
plugin._.dep = nil
|
plugin._.dep = nil
|
||||||
end
|
end
|
||||||
plugin._.top = nil
|
end
|
||||||
return plugin
|
return p
|
||||||
end, plugins)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe("plugin spec url/name", function()
|
describe("plugin spec url/name", function()
|
||||||
|
@ -37,16 +28,8 @@ describe("plugin spec url/name", function()
|
||||||
{ { "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" } },
|
||||||
{ { "https://foo.bar" }, { [1] = "https://foo.bar", name = "foo.bar", url = "https://foo.bar" } },
|
{ { "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", 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" } },
|
{ { "foo/bar", url = "123" }, { [1] = "foo/bar", name = "123", url = "123" } },
|
||||||
{ { url = "https://foobar" }, { name = "foobar", url = "https://foobar" } },
|
{ { 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" } },
|
{ { 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" } },
|
||||||
{ { { { "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" } },
|
||||||
|
@ -54,23 +37,15 @@ describe("plugin spec url/name", function()
|
||||||
|
|
||||||
for _, test in ipairs(tests) do
|
for _, test in ipairs(tests) do
|
||||||
test[2]._ = {}
|
test[2]._ = {}
|
||||||
it("parses " .. inspect(test[1]), function()
|
it("parses " .. vim.inspect(test[1]):gsub("%s+", " "), function()
|
||||||
if not test[2].dir then
|
if not test[2].dir then
|
||||||
test[2].dir = Config.options.root .. "/" .. test[2].name
|
test[2].dir = Config.options.root .. "/" .. test[2].name
|
||||||
end
|
end
|
||||||
local spec = Plugin.Spec.new(test[1])
|
local spec = Plugin.Spec.new(test[1])
|
||||||
local all = vim.deepcopy(spec.plugins)
|
local plugins = vim.tbl_values(spec.plugins)
|
||||||
local plugins = vim.tbl_values(all)
|
plugins[1]._ = {}
|
||||||
plugins = vim.tbl_map(function(plugin)
|
assert(#spec.notifs == 0)
|
||||||
plugin._ = {}
|
assert.equal(1, #plugins)
|
||||||
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])
|
assert.same(test[2], plugins[1])
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
@ -103,40 +78,7 @@ describe("plugin spec dir", function()
|
||||||
for _, test in ipairs(tests) do
|
for _, test in ipairs(tests) do
|
||||||
local dir = vim.fn.expand(test[1])
|
local dir = vim.fn.expand(test[1])
|
||||||
local input = vim.list_slice(test, 2)
|
local input = vim.list_slice(test, 2)
|
||||||
it("parses dir " .. inspect(input), function()
|
it("parses dir " .. vim.inspect(input):gsub("%s+", " "), 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 spec = Plugin.Spec.new(input)
|
||||||
local plugins = vim.tbl_values(spec.plugins)
|
local plugins = vim.tbl_values(spec.plugins)
|
||||||
assert(spec:report() == 0)
|
assert(spec:report() == 0)
|
||||||
|
@ -172,14 +114,16 @@ describe("plugin spec opt", function()
|
||||||
for _, plugin in pairs(spec.plugins) do
|
for _, plugin in pairs(spec.plugins) do
|
||||||
plugin.dir = nil
|
plugin.dir = nil
|
||||||
end
|
end
|
||||||
assert.same({
|
assert.same(clean(spec.plugins), {
|
||||||
bar = {
|
bar = {
|
||||||
|
"foo/bar",
|
||||||
_ = {},
|
_ = {},
|
||||||
dependencies = { "dep1", "dep2" },
|
dependencies = { "dep1", "dep2" },
|
||||||
name = "bar",
|
name = "bar",
|
||||||
url = "https://github.com/foo/bar.git",
|
url = "https://github.com/foo/bar.git",
|
||||||
},
|
},
|
||||||
dep1 = {
|
dep1 = {
|
||||||
|
"foo/dep1",
|
||||||
_ = {
|
_ = {
|
||||||
dep = true,
|
dep = true,
|
||||||
},
|
},
|
||||||
|
@ -187,13 +131,14 @@ describe("plugin spec opt", function()
|
||||||
url = "https://github.com/foo/dep1.git",
|
url = "https://github.com/foo/dep1.git",
|
||||||
},
|
},
|
||||||
dep2 = {
|
dep2 = {
|
||||||
|
"foo/dep2",
|
||||||
_ = {
|
_ = {
|
||||||
dep = true,
|
dep = true,
|
||||||
},
|
},
|
||||||
name = "dep2",
|
name = "dep2",
|
||||||
url = "https://github.com/foo/dep2.git",
|
url = "https://github.com/foo/dep2.git",
|
||||||
},
|
},
|
||||||
}, clean(spec.plugins))
|
})
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -201,13 +146,13 @@ describe("plugin spec opt", function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
Handler.init()
|
Handler.init()
|
||||||
end)
|
end)
|
||||||
|
it("handles dep names", function()
|
||||||
Config.options.defaults.lazy = false
|
Config.options.defaults.lazy = false
|
||||||
local tests = {
|
local tests = {
|
||||||
{ { "foo/bar", dependencies = { { "dep1" }, "foo/dep2" } }, "foo/dep1" },
|
{ { "foo/bar", dependencies = { { "dep1" }, "foo/dep2" } }, "foo/dep1" },
|
||||||
{ "foo/dep1", { "foo/bar", dependencies = { { "dep1" }, "foo/dep2" } } },
|
{ "foo/dep1", { "foo/bar", dependencies = { { "dep1" }, "foo/dep2" } } },
|
||||||
}
|
}
|
||||||
for _, test in ipairs(tests) do
|
for _, test in ipairs(tests) do
|
||||||
it("handles dep names " .. inspect(test), function()
|
|
||||||
local spec = Plugin.Spec.new(vim.deepcopy(test))
|
local spec = Plugin.Spec.new(vim.deepcopy(test))
|
||||||
assert(#spec.notifs == 0)
|
assert(#spec.notifs == 0)
|
||||||
Config.plugins = spec.plugins
|
Config.plugins = spec.plugins
|
||||||
|
@ -216,74 +161,31 @@ describe("plugin spec opt", function()
|
||||||
for _, plugin in pairs(spec.plugins) do
|
for _, plugin in pairs(spec.plugins) do
|
||||||
plugin.dir = nil
|
plugin.dir = nil
|
||||||
end
|
end
|
||||||
assert.same({
|
assert.same(clean(spec.plugins), {
|
||||||
bar = {
|
bar = {
|
||||||
|
"foo/bar",
|
||||||
_ = {},
|
_ = {},
|
||||||
dependencies = { "dep1", "dep2" },
|
dependencies = { "dep1", "dep2" },
|
||||||
name = "bar",
|
name = "bar",
|
||||||
url = "https://github.com/foo/bar.git",
|
url = "https://github.com/foo/bar.git",
|
||||||
},
|
},
|
||||||
dep1 = {
|
dep1 = {
|
||||||
|
"foo/dep1",
|
||||||
_ = {},
|
_ = {},
|
||||||
name = "dep1",
|
name = "dep1",
|
||||||
url = "https://github.com/foo/dep1.git",
|
url = "https://github.com/foo/dep1.git",
|
||||||
},
|
},
|
||||||
dep2 = {
|
dep2 = {
|
||||||
|
"foo/dep2",
|
||||||
_ = {
|
_ = {
|
||||||
dep = true,
|
dep = true,
|
||||||
},
|
},
|
||||||
name = "dep2",
|
name = "dep2",
|
||||||
url = "https://github.com/foo/dep2.git",
|
url = "https://github.com/foo/dep2.git",
|
||||||
},
|
},
|
||||||
}, clean(spec.plugins))
|
})
|
||||||
|
end
|
||||||
end)
|
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()
|
it("handles opt from dep", function()
|
||||||
Config.options.defaults.lazy = false
|
Config.options.defaults.lazy = false
|
||||||
|
@ -340,7 +242,7 @@ describe("plugin spec opt", function()
|
||||||
assert(#spec.notifs == 0)
|
assert(#spec.notifs == 0)
|
||||||
assert(vim.tbl_count(spec.plugins) == 1)
|
assert(vim.tbl_count(spec.plugins) == 1)
|
||||||
Handler.resolve(spec.plugins.bar)
|
Handler.resolve(spec.plugins.bar)
|
||||||
-- vim.print(spec.plugins.bar._.handlers)
|
vim.print(spec.plugins.bar._.handlers)
|
||||||
local events = vim.tbl_keys(spec.plugins.bar._.handlers.event or {})
|
local events = vim.tbl_keys(spec.plugins.bar._.handlers.event or {})
|
||||||
assert(type(events) == "table")
|
assert(type(events) == "table")
|
||||||
assert(#events == 2)
|
assert(#events == 2)
|
||||||
|
@ -455,6 +357,7 @@ describe("plugin spec opt", function()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe("plugin opts", function()
|
describe("plugin opts", function()
|
||||||
|
it("correctly parses opts", function()
|
||||||
---@type {spec:LazySpec, opts:table}[]
|
---@type {spec:LazySpec, opts:table}[]
|
||||||
local tests = {
|
local tests = {
|
||||||
{
|
{
|
||||||
|
@ -488,12 +391,11 @@ describe("plugin opts", function()
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test in ipairs(tests) do
|
for _, test in ipairs(tests) do
|
||||||
it("correctly parses opts for " .. inspect(test.spec), function()
|
|
||||||
local spec = Plugin.Spec.new(test.spec)
|
local spec = Plugin.Spec.new(test.spec)
|
||||||
assert(spec.plugins.foo)
|
assert(spec.plugins.foo)
|
||||||
assert.same(test.opts, Plugin.values(spec.plugins.foo, "opts"))
|
assert.same(test.opts, Plugin.values(spec.plugins.foo, "opts"))
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe("plugin spec", function()
|
describe("plugin spec", function()
|
||||||
|
|
|
@ -5,7 +5,6 @@ local Util = require("lazy.util")
|
||||||
describe("util", function()
|
describe("util", function()
|
||||||
local rtp = vim.opt.rtp:get()
|
local rtp = vim.opt.rtp:get()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
---@type vim.Option
|
|
||||||
vim.opt.rtp = rtp
|
vim.opt.rtp = rtp
|
||||||
for k, v in pairs(package.loaded) do
|
for k, v in pairs(package.loaded) do
|
||||||
if k:find("^foobar") then
|
if k:find("^foobar") then
|
||||||
|
|
36
tests/init.lua
Normal file
36
tests/init.lua
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
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.uv.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")
|
||||||
|
vim.env.XDG_CONFIG_HOME = M.root(".tests/config")
|
||||||
|
vim.env.XDG_DATA_HOME = M.root(".tests/data")
|
||||||
|
vim.env.XDG_STATE_HOME = M.root(".tests/state")
|
||||||
|
vim.env.XDG_CACHE_HOME = M.root(".tests/cache")
|
||||||
|
end
|
||||||
|
|
||||||
|
M.setup()
|
|
@ -1,19 +0,0 @@
|
||||||
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)
|
|
|
@ -1,4 +1,3 @@
|
||||||
local Async = require("lazy.async")
|
|
||||||
local Runner = require("lazy.manage.runner")
|
local Runner = require("lazy.manage.runner")
|
||||||
|
|
||||||
describe("runner", function()
|
describe("runner", function()
|
||||||
|
@ -31,11 +30,11 @@ describe("runner", function()
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
package.loaded["lazy.manage.task.test"]["async" .. i] = {
|
package.loaded["lazy.manage.task.test"]["async" .. i] = {
|
||||||
---@async
|
|
||||||
---@param task LazyTask
|
---@param task LazyTask
|
||||||
run = function(task)
|
run = function(task)
|
||||||
Async.yield()
|
task:schedule(function()
|
||||||
table.insert(runs, { plugin = task.plugin.name, task = task.name })
|
table.insert(runs, { plugin = task.plugin.name, task = task.name })
|
||||||
|
end)
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -65,7 +64,7 @@ describe("runner", function()
|
||||||
local runner = Runner.new({ plugins = plugins, pipeline = { "test.test1", "test.skip", "test.test2" } })
|
local runner = Runner.new({ plugins = plugins, pipeline = { "test.test1", "test.skip", "test.test2" } })
|
||||||
runner:start()
|
runner:start()
|
||||||
runner:wait()
|
runner:wait()
|
||||||
assert.equal(4, #runs, runs)
|
assert.equal(4, #runs)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("handles opts", function()
|
it("handles opts", function()
|
||||||
|
|
|
@ -14,7 +14,6 @@ describe("semver version", function()
|
||||||
["1.2.3+build"] = { major = 1, minor = 2, patch = 3, build = "build" },
|
["1.2.3+build"] = { major = 1, minor = 2, patch = 3, build = "build" },
|
||||||
}
|
}
|
||||||
for input, output in pairs(tests) do
|
for input, output in pairs(tests) do
|
||||||
output.input = input
|
|
||||||
it("correctly parses " .. input, function()
|
it("correctly parses " .. input, function()
|
||||||
assert.same(output, v(input))
|
assert.same(output, v(input))
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -1,82 +1,96 @@
|
||||||
--# selene:allow(incorrect_standard_library_use)
|
--# selene:allow(incorrect_standard_library_use)
|
||||||
local Async = require("lazy.async")
|
|
||||||
local Task = require("lazy.manage.task")
|
local Task = require("lazy.manage.task")
|
||||||
|
|
||||||
describe("task", function()
|
describe("task", function()
|
||||||
local plugin = { name = "test", _ = {} }
|
local plugin = { name = "test", _ = {} }
|
||||||
|
|
||||||
---@type {done?:boolean, error:string?}
|
local done = false
|
||||||
local task_result = {}
|
---@type string?
|
||||||
|
local error
|
||||||
|
|
||||||
local opts = {
|
local opts = {
|
||||||
---@param task LazyTask
|
|
||||||
on_done = function(task)
|
on_done = function(task)
|
||||||
task_result = { done = true, error = task.error }
|
done = true
|
||||||
|
error = task.error
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
before_each(function()
|
before_each(function()
|
||||||
task_result = {}
|
done = false
|
||||||
|
error = nil
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("simple function", function()
|
it("simple function", function()
|
||||||
local task = Task.new(plugin, "test", function() end, opts)
|
local task = Task.new(plugin, "test", function() end, opts)
|
||||||
assert(task:running())
|
assert(not task:has_started())
|
||||||
task:wait()
|
assert(not task:is_running())
|
||||||
assert(not task:running())
|
task:start()
|
||||||
assert(task_result.done)
|
assert(not task:is_running())
|
||||||
|
assert(task:is_done())
|
||||||
|
assert(done)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("detects errors", function()
|
it("detects errors", function()
|
||||||
local task = Task.new(plugin, "test", function()
|
local task = Task.new(plugin, "test", function()
|
||||||
error("test")
|
error("test")
|
||||||
end, opts)
|
end, opts)
|
||||||
assert(task:running())
|
assert(not task:has_started())
|
||||||
task:wait()
|
assert(not task:is_running())
|
||||||
assert(not task:running())
|
task:start()
|
||||||
assert(task_result.done)
|
assert(task:is_done())
|
||||||
assert(task_result.error)
|
assert(not task:is_running())
|
||||||
assert(task:has_errors() and task:output(vim.log.levels.ERROR):find("test"))
|
assert(done)
|
||||||
|
assert(error)
|
||||||
|
assert(task.error and task.error:find("test"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("async", function()
|
it("schedule", function()
|
||||||
local running = true
|
local running = false
|
||||||
---@async
|
local task = Task.new(plugin, "test", function(task)
|
||||||
local task = Task.new(plugin, "test", function()
|
running = true
|
||||||
Async.yield()
|
task:schedule(function()
|
||||||
running = false
|
running = false
|
||||||
|
end)
|
||||||
end, opts)
|
end, opts)
|
||||||
assert(task:running())
|
assert(not task:is_running())
|
||||||
|
assert(not task:has_started())
|
||||||
|
task:start()
|
||||||
assert(running)
|
assert(running)
|
||||||
assert(task:running())
|
assert(#task._running == 1)
|
||||||
|
assert(task:is_running())
|
||||||
|
assert(not task:is_done())
|
||||||
task:wait()
|
task:wait()
|
||||||
assert(not running)
|
assert(task:is_done())
|
||||||
assert(not task:running())
|
assert(not task:is_running())
|
||||||
assert(task_result.done)
|
assert(done)
|
||||||
assert(not task:has_errors())
|
assert(not task.error)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("spawn errors", function()
|
it("spawn errors", function()
|
||||||
local task = Task.new(plugin, "spawn_errors", function(task)
|
local task = Task.new(plugin, "test", function(task)
|
||||||
task:spawn("foobar")
|
task:spawn("foobar")
|
||||||
end, opts)
|
end, opts)
|
||||||
assert(task:running())
|
assert(not task:is_running())
|
||||||
task:wait()
|
task:start()
|
||||||
assert(not task:running())
|
assert(not task:is_running())
|
||||||
assert(task_result.done)
|
assert(done)
|
||||||
assert(task:has_errors() and task:output(vim.log.levels.ERROR):find("Failed to spawn"), task:output())
|
assert(task.error and task.error:find("Failed to spawn"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("spawn", function()
|
it("spawn", function()
|
||||||
local task = Task.new(plugin, "test", function(task)
|
local task = Task.new(plugin, "test", function(task)
|
||||||
task:spawn("echo", { args = { "foo" } })
|
task:spawn("echo", { args = { "foo" } })
|
||||||
end, opts)
|
end, opts)
|
||||||
assert(task:running())
|
assert(not task:is_running())
|
||||||
assert(task:running())
|
assert(not task:has_started())
|
||||||
|
task:start()
|
||||||
|
assert(task:has_started())
|
||||||
|
assert(task:is_running())
|
||||||
task:wait()
|
task:wait()
|
||||||
assert.same(task:output(), "foo")
|
assert(task:is_done())
|
||||||
assert(task_result.done)
|
assert.same(task.output, "foo\n")
|
||||||
assert(not task:has_errors())
|
assert(done)
|
||||||
|
assert(not task.error)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("spawn 2x", function()
|
it("spawn 2x", function()
|
||||||
|
@ -84,11 +98,12 @@ describe("task", function()
|
||||||
task:spawn("echo", { args = { "foo" } })
|
task:spawn("echo", { args = { "foo" } })
|
||||||
task:spawn("echo", { args = { "bar" } })
|
task:spawn("echo", { args = { "bar" } })
|
||||||
end, opts)
|
end, opts)
|
||||||
assert(task:running())
|
assert(not task:is_running())
|
||||||
assert(task:running())
|
task:start()
|
||||||
|
assert(task:is_running())
|
||||||
task:wait()
|
task:wait()
|
||||||
assert(task:output() == "foo\nbar" or task:output() == "bar\nfoo", task:output())
|
assert(task.output == "foo\nbar\n" or task.output == "bar\nfoo\n")
|
||||||
assert(task_result.done)
|
assert(done)
|
||||||
assert(not task:has_errors())
|
assert(not task.error)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
#!/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() },
|
|
||||||
},
|
|
||||||
})
|
|
3
tests/run
Executable file
3
tests/run
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
nvim --headless -u tests/init.lua -c "PlenaryBustedDirectory tests {minimal_init = 'tests//init.lua', sequential = true}"
|
42
vim.toml
42
vim.toml
|
@ -8,14 +8,42 @@ any = true
|
||||||
[jit]
|
[jit]
|
||||||
any = true
|
any = true
|
||||||
|
|
||||||
[assert]
|
[[describe.args]]
|
||||||
|
type = "string"
|
||||||
|
[[describe.args]]
|
||||||
|
type = "function"
|
||||||
|
|
||||||
|
[[it.args]]
|
||||||
|
type = "string"
|
||||||
|
[[it.args]]
|
||||||
|
type = "function"
|
||||||
|
|
||||||
|
[[before_each.args]]
|
||||||
|
type = "function"
|
||||||
|
[[after_each.args]]
|
||||||
|
type = "function"
|
||||||
|
|
||||||
|
[assert.is_not]
|
||||||
any = true
|
any = true
|
||||||
|
|
||||||
[describe]
|
[[assert.equals.args]]
|
||||||
any = true
|
type = "any"
|
||||||
|
[[assert.equals.args]]
|
||||||
|
type = "any"
|
||||||
|
[[assert.equals.args]]
|
||||||
|
type = "any"
|
||||||
|
required = false
|
||||||
|
|
||||||
[it]
|
[[assert.same.args]]
|
||||||
any = true
|
type = "any"
|
||||||
|
[[assert.same.args]]
|
||||||
|
type = "any"
|
||||||
|
|
||||||
[before_each.args]
|
[[assert.truthy.args]]
|
||||||
any = true
|
type = "any"
|
||||||
|
|
||||||
|
[[assert.spy.args]]
|
||||||
|
type = "any"
|
||||||
|
|
||||||
|
[[assert.stub.args]]
|
||||||
|
type = "any"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue