Compare commits
21 Commits
26ef7289f6
...
lazy
Author | SHA1 | Date | |
---|---|---|---|
70853bd01e
|
|||
9d4322572c
|
|||
3b33a604d8
|
|||
5aff147731
|
|||
edf32fbf06
|
|||
adec93b7f4
|
|||
1cd5f63f8e
|
|||
8e46eddecd
|
|||
542298c1fe
|
|||
cfc3f08d53
|
|||
1c2f49fcfa
|
|||
f6209048f1
|
|||
5bd30d9397
|
|||
1538046b6f
|
|||
5deffca36e
|
|||
318a86d786
|
|||
5541a656e2
|
|||
59a963a5c5
|
|||
cd43b3b853
|
|||
585f04c745
|
|||
a13d616da5
|
11
.githooks/pre-commit
Executable file
11
.githooks/pre-commit
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Running tests before commit..."
|
||||
|
||||
# run tests
|
||||
make test || {
|
||||
echo "Tests failed. Commit aborted."
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Tests passed. Proceeding with commit."
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
.DS_Store
|
||||
doc/tags
|
||||
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 squibid
|
||||
Copyright (c) 2023-2025 squibid
|
||||
Copyright (c) 2021-2023 chiya.dev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
4
Makefile
Normal file
4
Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
test:
|
||||
nvim --headless -c "PlenaryBustedDirectory tests/ {minimal_init = './tests/minit.lua'}"
|
||||
|
||||
.PHONY: test
|
@ -482,6 +482,14 @@ require "dep" {
|
||||
- Lazy loading nvim-cmp doesn't work as the external sources don't get reconized
|
||||
by nvim-cmp when it's loaded.
|
||||
|
||||
## Contributing
|
||||
|
||||
When contributing you may choose to run tests before commiting changes, if that
|
||||
is so you may choose to run the following:
|
||||
```sh
|
||||
git config core.hooksPath .githooks
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
dep is licensed under the [MIT License](LICENSE).
|
||||
|
670
doc/dep.txt
Normal file
670
doc/dep.txt
Normal file
@ -0,0 +1,670 @@
|
||||
*dep.txt* Declarative Package Manager 02-Jul-2025
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *dep-table-of-contents*
|
||||
|
||||
1. Introduction |dep|
|
||||
2. Setup |dep-setup|
|
||||
3. Specs |dep-spec|
|
||||
- Package Spec |dep-package-spec|
|
||||
- Module Spec |dep-module-spec|
|
||||
4. Lazy Loading |dep-lazy-loading|
|
||||
- Lazy Loading API |dep-lazy-loading-api|
|
||||
- Lazy Loading API Shorthands |dep-lazy-loading-api-shorthands|
|
||||
5. Commands |dep-commands|
|
||||
6. Examples |dep-examples|
|
||||
- Declaring Dependencies |dep-examples-declaring-dependencies|
|
||||
- Modules |dep-examples-modules|
|
||||
- Lazy Loading |dep-examples-lazy-loading|
|
||||
7. Credits & License |dep-credits|
|
||||
|
||||
==============================================================================
|
||||
1. Introduction *dep*
|
||||
|
||||
A versatile, declarative and correct neovim package manager in Lua. Originally
|
||||
written for personal use by luaneko. Adapted by squibid for general use.
|
||||
|
||||
What does that mean?
|
||||
|
||||
1. `versatile` - packages can be declared in any Lua file in any order of your
|
||||
liking.
|
||||
2. `declarative` - packages are declared using simple Lua tables.
|
||||
3. `correct` - packages are always loaded in a correct and consistent order
|
||||
(barring any lazy loading).
|
||||
|
||||
In addition to the above dep has been built to be completely in control of you,
|
||||
the user. With the help of lazy loading you can choose when your plugin loads
|
||||
down to the finest detail (examples may be found below).
|
||||
|
||||
==============================================================================
|
||||
2. Setup *dep-setup*
|
||||
|
||||
Put the following anywhere before any actual use of dep.
|
||||
|
||||
>lua
|
||||
local path = vim.fn.stdpath("data") .. "/site/pack/deps/opt/dep"
|
||||
|
||||
if vim.fn.empty(vim.fn.glob(path)) > 0 then
|
||||
vim.fn.system({
|
||||
"git",
|
||||
"clone",
|
||||
"--depth=1",
|
||||
"https://git.squi.bid/squibid/dep",
|
||||
path,
|
||||
})
|
||||
end
|
||||
|
||||
vim.cmd("packadd dep")
|
||||
<
|
||||
|
||||
==============================================================================
|
||||
3. Specs *dep-spec*
|
||||
|
||||
dep uses a variation of specifications to ensure everything works smoothly.
|
||||
This includes a basic spec used when setting up dep:
|
||||
>lua
|
||||
require("dep") {
|
||||
-- [string] Specifies when dep should automatically synchronize.
|
||||
-- "never": disable this behavior
|
||||
-- "new": only install newly declared packages (default)
|
||||
-- "always": synchronize all packages on startup
|
||||
sync = "new",
|
||||
|
||||
-- [array] Specifies the modules to load package specifications from.
|
||||
-- Defaults to an empty table.
|
||||
-- Items can be either an array of package specifications,
|
||||
-- or a string that indicates the name of the module from which the array
|
||||
-- of package specifications is loaded.
|
||||
--
|
||||
-- "."'s are added between the prefix and module names as required. In
|
||||
-- addition if there is only a prefix and no modules supplied then dep
|
||||
-- automatically loads all lua files in the directory.
|
||||
modules = {
|
||||
-- [string] Prefix string to prepend to all module names. This is
|
||||
-- optional.
|
||||
prefix = "",
|
||||
|
||||
-- [string] module names
|
||||
...
|
||||
},
|
||||
|
||||
-- [table|string] package specification(s)
|
||||
...
|
||||
}
|
||||
<
|
||||
PACKAGE SPEC *dep-package-spec*
|
||||
>lua
|
||||
{
|
||||
-- [string] Specifies the full name of the package.
|
||||
-- This is the only required field; all other fields are optional.
|
||||
"user/package",
|
||||
|
||||
-- [function] Code to run before the package is loaded into neovim.
|
||||
setup = function()
|
||||
vim.g.package_config = ...
|
||||
end,
|
||||
|
||||
-- [function] Code to run after the package is loaded into neovim.
|
||||
load = function()
|
||||
require "package".setup(...)
|
||||
end,
|
||||
|
||||
-- [function] Code to run after the package is installed or updated.
|
||||
config = function()
|
||||
os.execute(...)
|
||||
end,
|
||||
|
||||
-- [function|true] Code used to determine when the package should be
|
||||
-- loaded.
|
||||
lazy = function(load)
|
||||
load:cmd("LoadPackage")
|
||||
end,
|
||||
|
||||
-- [string] Overrides the short name of the package.
|
||||
-- Defaults to a substring of the full name after '/'.
|
||||
as = "custom_package",
|
||||
|
||||
-- [string] Overrides the URL of the git repository to clone.
|
||||
-- Defaults to "https://github.com/{full_name}.git".
|
||||
url = "https://git.squi.bid/user/package.git",
|
||||
|
||||
-- [string] Overrides the source in which the package is gotten
|
||||
-- from. This is not set by default.
|
||||
path = "~/my-local-package/",
|
||||
|
||||
-- [string] Overrides the name of the branch to clone.
|
||||
-- Defaults to whatever the remote configured as their HEAD, which is
|
||||
-- usually "master".
|
||||
branch = "develop",
|
||||
|
||||
-- [string] Overrides the commit ref to target
|
||||
-- Defaults to the latest commit on the current branch
|
||||
commit = "e76cb03",
|
||||
|
||||
-- [boolean] Prevents the package from being loaded.
|
||||
disable = true,
|
||||
|
||||
-- [boolean] Prevents the package from being updated.
|
||||
pin = true,
|
||||
|
||||
-- [string|array] Specifies requirements that must be loaded before the
|
||||
-- package. If given a string, it is wrapped into an array.
|
||||
reqs = {...},
|
||||
|
||||
-- [string|array] Specifies dependents that must be loaded after the
|
||||
-- package. If given a string, it is wrapped into an array.
|
||||
deps = {...}
|
||||
}
|
||||
<
|
||||
MODULE SPEC *dep-module-spec*
|
||||
>lua
|
||||
{
|
||||
-- [string] Specifies a name for the module
|
||||
name = "a name",
|
||||
|
||||
-- [string] Specifies a description of the module
|
||||
desc = "a description of the module",
|
||||
|
||||
-- [boolean] Prevents all packages in the module from being loaded.
|
||||
disable = false,
|
||||
|
||||
-- [table|string] package specification(s)
|
||||
...
|
||||
}
|
||||
<
|
||||
More information on the package specifications may be found in
|
||||
|dep-package-spec|.
|
||||
|
||||
==============================================================================
|
||||
4. Lazy Loading *dep-lazy-loading*
|
||||
|
||||
Lazy loading is important for making sure neovim can load nice and fast unlike
|
||||
a certain bloated IDE. It has a seperate section in this documentation to
|
||||
ensure that you can use it to it's full extent.
|
||||
|
||||
If you refer to the |dep-package-spec| you'll notice the `lazy` flag which may
|
||||
be used to conditionally load a package. When it is set to a function you
|
||||
choose when it runs and more information on that may be found in
|
||||
|dep-lazy-loading-api|. In addition to setting it to a function you may set it
|
||||
to `true` in which case dep takes care of loading it for you.
|
||||
|
||||
When setting a colorscheme dep checks to make sure that the plugin is loaded,
|
||||
therefore it's recommended that you make use of the `lazy` flags ability to be
|
||||
set to `true` by setting any colorscheme that you have installed, but do not
|
||||
use as your main one to lazy.
|
||||
|
||||
LAZY LOADING API *dep-lazy-loading-api*
|
||||
|
||||
Within the |dep-package-spec| the lazy flag when set to a function takes one
|
||||
argument `load` which is a class containing loading functions. For the
|
||||
following examples assume that `load` is set to the class which may be found
|
||||
within `lua/dep/lazy/loader/init.lua`.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
LOAD:CMD *dep-lazy-loading-api-cmd*
|
||||
|
||||
`load:cmd` is a function which allows you to specify a command for the package
|
||||
to load on. It takes the similar arguments to |nvim_create_user_command()|
|
||||
with a key difference in what the command runs. The following is an example of
|
||||
what arguments the function takes:
|
||||
>lua
|
||||
load:cmd("Command", {})
|
||||
<
|
||||
Notice the missing 'command' argument which is found in
|
||||
|nvim_create_user_command|, this is replaced by a callback function. The above
|
||||
is equivalent to the following:
|
||||
>lua
|
||||
load:cmd("Command", {
|
||||
callback = function()
|
||||
load:cleanup()
|
||||
|
||||
if (rerun) then
|
||||
vim.cmd("Command")
|
||||
end
|
||||
end
|
||||
})
|
||||
<
|
||||
If you wish the second argument may be completely ommitted. Note the inclusion
|
||||
of a `rerun` field, this is a parameter which may be passed into the options table
|
||||
to re-run the binding after loading the package. You may choose to disable the
|
||||
built-in logic by passing false.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
LOAD:AUTO *dep-lazy-loading-api-auto*
|
||||
|
||||
`load:auto` is a function which allows you to specify an auto command for the
|
||||
package to load on. It takes the same arguments as |nvim_create_autocmd()|.
|
||||
The following is an example of using it:
|
||||
>lua
|
||||
load:auto("InsertEnter", {})
|
||||
<
|
||||
Just like with |nvim_create_autocmd()| you may choose to pass in a 'callback'
|
||||
by default the above is equivalent to the following:
|
||||
>lua
|
||||
load:auto("InsertEnter", {
|
||||
callback = function()
|
||||
load:cleanup()
|
||||
end
|
||||
})
|
||||
<
|
||||
As with `load:cmd` the second argument may be ommitted.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
LOAD:FT *dep-lazy-loading-api-ft*
|
||||
|
||||
`load:ft` is a function which allows you to specify a filetype for the package
|
||||
to load on. It takes one argument: 'filetype' like so:
|
||||
>lua
|
||||
load:ft("lua")
|
||||
<
|
||||
Which is equivalent to the following:
|
||||
>lua
|
||||
load:auto("FileType", {
|
||||
pattern = "lua",
|
||||
callback = function()
|
||||
load:cleanup()
|
||||
end
|
||||
})
|
||||
<
|
||||
Note that this is just an expansion of `load:auto` for your convenience.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
LOAD:KEYMAP *dep-lazy-loading-api-keymap*
|
||||
|
||||
`load:keymap` is a function which allows you to specify a keymap for the
|
||||
package to load on. It takes the similar arguments to |vim.keymap.set()| with a
|
||||
key difference in what the command runs. The following is an example of what
|
||||
arguments the function takes:
|
||||
>lua
|
||||
load:keymap("n", "<leader>p", {})
|
||||
<
|
||||
Notice the missing 'rhs' argument which is found in |vim.keymap.set|, this is
|
||||
replaced by a callback function. The above is equivalent to the following:
|
||||
>lua
|
||||
load:keymap("n", "<leader>p", {
|
||||
callback = function()
|
||||
-- register keymap unload
|
||||
load:cleanup()
|
||||
|
||||
-- call the keymap after the user has mapped it
|
||||
if type(rerun) == "function" then
|
||||
rerun()
|
||||
elseif rerun then
|
||||
local keys = vim.api.nvim_replace_termcodes(bind, true, false, true)
|
||||
vim.api.nvim_input(keys)
|
||||
end
|
||||
end
|
||||
})
|
||||
<
|
||||
Note the inclusion of a `rerun` field, this is a parameter which may be passed
|
||||
into the options table to re-run the binding after loading the package. You
|
||||
may choose to include your own logic by passing a function to the `rerun`
|
||||
field or disable the built-in logic by passing false.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
LOAD:PLUGIN *dep-lazy-loading-api-plugin*
|
||||
|
||||
`load:plugin` is a function which allows you to specify another plugin for the
|
||||
package to load after. It takes two arguments: `plugin` which is the name of
|
||||
the plugin you want to follow like: 'user/package'. The second argument is
|
||||
`opts` which is a table with one option: `callback` which is a function. The
|
||||
following is an example:
|
||||
>lua
|
||||
load:plugin("user/package", {})
|
||||
<
|
||||
Which is the same as:
|
||||
>lua
|
||||
load:plugin("user/package", {
|
||||
callback = function()
|
||||
self:cleanup()
|
||||
end
|
||||
})
|
||||
<
|
||||
When 'user/package' is already loaded the `callback` is called immediately.
|
||||
|
||||
LAZY LOADING API SHORTHANDS *dep-lazy-loading-api-shorthands*
|
||||
|
||||
On occasion you may wish to only define one condition for the package to load.
|
||||
When that is the case you may choose to use the built-in shorthands. By
|
||||
loading them:
|
||||
>lua
|
||||
require("dep.lazy.loader.short")
|
||||
<
|
||||
The shorthands are very similar to those found in |dep-lazy-loading-api| with
|
||||
a key exception: instead of running the functions within the body of a
|
||||
function set as the lazy field to a package specification this is the lazy
|
||||
field and may be use like so:
|
||||
>lua
|
||||
{ "user/package",
|
||||
lazy = require("dep.lazy.loader.short").cmd("Command")
|
||||
}
|
||||
<
|
||||
And you may of course put the shorthands in a variable to make this actually
|
||||
shorter:
|
||||
>lua
|
||||
local short = require("dep.lazy.loader.short")
|
||||
{ "user/package",
|
||||
lazy = short.cmd("Command")
|
||||
}
|
||||
<
|
||||
==============================================================================
|
||||
5. Commands *dep-commands*
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
SYNC ALL PLUGINS *:DepSync*
|
||||
- installs new packages, updates packages to the latest versions,
|
||||
cleans removed packages and reloads packages as necessary.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
CLEAN REMOVED PLUGINS *:DepClean*
|
||||
- cleans removed packages.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
RELOAD ALL PLUGINS *:DepReload*
|
||||
- reloads all packages.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
OPEN THE UI *:DepUi*
|
||||
- opens the ui.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
OPEN THE LOG *:DepLog*
|
||||
- opens the log file.
|
||||
|
||||
==============================================================================
|
||||
6. Examples *dep-examples*
|
||||
|
||||
When a string is given where a package specification table is expected, it is
|
||||
assumed to be the package's full name.
|
||||
|
||||
>lua
|
||||
require("dep") {
|
||||
-- these two are equivalent
|
||||
"user/package",
|
||||
{ "user/package" },
|
||||
}
|
||||
<
|
||||
|
||||
A package can be declared multiple times. Multiple declarations of the same
|
||||
package are combined into one. This is useful when declaring dependencies,
|
||||
which is explored later.
|
||||
|
||||
>lua
|
||||
require("dep") {
|
||||
{ "user/package",
|
||||
reqs = "user/dependency",
|
||||
disabled = true,
|
||||
config = function()
|
||||
print("my config hook")
|
||||
end
|
||||
},
|
||||
{ "user/package",
|
||||
requires = "user/another_dependency",
|
||||
deps = "user/dependent",
|
||||
disabled = false,
|
||||
config = function()
|
||||
os.execute("make")
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
-- the above is equivalent to
|
||||
require("dep") {
|
||||
{ "user/package",
|
||||
reqs = { "user/dependency", "user/another_dependency" },
|
||||
deps = "user/dependent",
|
||||
disabled = true,
|
||||
config = function()
|
||||
print("my config hook")
|
||||
os.execute("make")
|
||||
end
|
||||
}
|
||||
}
|
||||
<
|
||||
DECLARING DEPENDENCIES *dep-examples-declaring-dependencies*
|
||||
|
||||
The dependencies and dependents declared in a package specification are
|
||||
themselves package specifications. If a dependency or dependent is declared
|
||||
multiple times, they are combined into one just like normal package
|
||||
specifications.
|
||||
>lua
|
||||
require("dep") {
|
||||
{ "user/package",
|
||||
reqs = {
|
||||
{ "user/dependency1",
|
||||
reqs = "user/dependency2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-- the above is equivalent to
|
||||
require("dep") {
|
||||
{ "user/dependency2",
|
||||
deps = {
|
||||
{ "user/dependency1",
|
||||
deps = "user/package"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-- which is equivalent to
|
||||
require("dep") {
|
||||
{ "user/dependency1",
|
||||
reqs = "user/dependency2",
|
||||
deps = "user/package"
|
||||
}
|
||||
}
|
||||
|
||||
-- which is equivalent to
|
||||
require("dep") {
|
||||
{ "user/dependency1",
|
||||
reqs = "user/dependency2"
|
||||
},
|
||||
{ "user/package",
|
||||
reqs = "user/dependency1"
|
||||
}
|
||||
}
|
||||
|
||||
-- which is equivalent to
|
||||
require("dep") {
|
||||
{ "user/dependency2",
|
||||
deps = "user/dependency1"
|
||||
},
|
||||
{ "user/dependency1",
|
||||
deps = "user/package"
|
||||
}
|
||||
}
|
||||
|
||||
-- all of the above are guaranteed to load in the following order:
|
||||
-- dependency2, dependency1, package
|
||||
<
|
||||
If dep detects a circular dependency cycle, it reports the problematic packages
|
||||
instead of hanging or crashing.
|
||||
>lua
|
||||
-- this throws an error saying package1 depends on package2 which depends on
|
||||
-- package1
|
||||
require("dep") {
|
||||
{ "user/package1",
|
||||
reqs = "user/package2"
|
||||
},
|
||||
{ "user/package2",
|
||||
reqs = "user/package1"
|
||||
}
|
||||
}
|
||||
<
|
||||
A dependency can be marked as disabled, which disables all dependents
|
||||
automatically.
|
||||
>lua
|
||||
require("dep") {
|
||||
{ "user/dependency",
|
||||
disabled = true
|
||||
},
|
||||
{ "user/package1",
|
||||
disabled = true, -- implied
|
||||
reqs = "user/dependency"
|
||||
},
|
||||
{ "user/package2",
|
||||
disabled = true, -- implied
|
||||
reqs = "user/dependency"
|
||||
}
|
||||
}
|
||||
<
|
||||
If a dependency fails to load for some reason, all of its dependents are
|
||||
guaranteed to not load.
|
||||
>lua
|
||||
require("dep") {
|
||||
{ "user/problematic",
|
||||
load = function()
|
||||
error("bad hook")
|
||||
end
|
||||
},
|
||||
{ "user/dependent",
|
||||
requires = "user/problematic",
|
||||
load = function()
|
||||
print "unreachable"
|
||||
end
|
||||
}
|
||||
}
|
||||
<
|
||||
|
||||
MODULES *dep-examples-modules*
|
||||
|
||||
Suppose you split your `init.lua` into two files `packages/search.lua` and
|
||||
`packages/vcs.lua`, which declare the packages telescope.nvim and vim-fugitive
|
||||
respectively.
|
||||
|
||||
>lua
|
||||
-- ~/.config/nvim/lua/packages/search.lua:
|
||||
return {
|
||||
{ "nvim-telescope/telescope.nvim",
|
||||
reqs = "nvim-lua/plenary.nvim"
|
||||
}
|
||||
}
|
||||
<
|
||||
>lua
|
||||
-- ~/.config/nvim/lua/packages/vcs.lua:
|
||||
return { "tpope/vim-fugitive" }
|
||||
<
|
||||
Package specifications from other modules can be loaded using the `modules`
|
||||
option.
|
||||
>lua
|
||||
require("dep") {
|
||||
modules = {
|
||||
prefix = "packages"
|
||||
}
|
||||
}
|
||||
|
||||
-- the above is equivalent to
|
||||
require("dep") {
|
||||
modules = {
|
||||
prefix = "packages.",
|
||||
"search",
|
||||
"vcs"
|
||||
}
|
||||
}
|
||||
|
||||
-- or
|
||||
require("dep") {
|
||||
modules = {
|
||||
"packages.search",
|
||||
"packages.vcs"
|
||||
}
|
||||
}
|
||||
|
||||
-- which is equivalent to
|
||||
local packages = {}
|
||||
|
||||
for _, package in ipairs(require "packages.search") do
|
||||
table.insert(packages, package)
|
||||
end
|
||||
|
||||
for _, package in ipairs(require "packages.vcs") do
|
||||
table.insert(packages, package)
|
||||
end
|
||||
|
||||
require("dep")(packages)
|
||||
|
||||
-- which is ultimately equivalent to
|
||||
require("dep") {
|
||||
{ "nvim-telescope/telescope.nvim",
|
||||
reqs = "nvim-lua/plenary.nvim"
|
||||
},
|
||||
"tpope/vim-fugitive"
|
||||
}
|
||||
|
||||
-- all of the above are guaranteed to load plenary.nvim before
|
||||
-- telescope.nvim. order of telescope.nvim and vim-fugitive is consistent but
|
||||
-- unspecified.
|
||||
<
|
||||
Entire modules can be marked as disabled, which disables all top-level packages
|
||||
declared in that module.
|
||||
>lua
|
||||
return {
|
||||
disable = true,
|
||||
{ "user/package",
|
||||
disabled = true, -- implied by module
|
||||
reqs = {
|
||||
{ "user/dependency",
|
||||
-- disabled = true -- not implied
|
||||
}
|
||||
},
|
||||
deps = {
|
||||
{ "user/dependent",
|
||||
disabled = true -- implied by dependency
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
<
|
||||
LAZY LOADING *dep-examples-lazy-loading*
|
||||
|
||||
Lazy loading is a very complicated topic, and therefore this part of the
|
||||
documentation assumes you have experience with regular package managment.
|
||||
Let's go over loading order, and how the lazy loader determines what needs to
|
||||
be loaded.
|
||||
|
||||
Let's say we have the following spec:
|
||||
>lua
|
||||
{ "user/package",
|
||||
lazy = true,
|
||||
deps = "user/dependent"
|
||||
}
|
||||
<
|
||||
This is the same as the following:
|
||||
>lua
|
||||
{ "user/package",
|
||||
lazy = true
|
||||
},
|
||||
|
||||
{ "user/dependent",
|
||||
reqs = "user/package",
|
||||
lazy = require("dep.lazy.loader.short").plugin("user/package")
|
||||
}
|
||||
<
|
||||
What you're seeing is implicit lazy loading. By default dep will lazy load
|
||||
dependents who are explicitly defined in the spec. Now if we we're to modify
|
||||
'user/dependent' like so:
|
||||
>lua
|
||||
{ "user/package",
|
||||
lazy = true
|
||||
},
|
||||
|
||||
{ "user/dependent",
|
||||
reqs = "user/package",
|
||||
lazy = function(load)
|
||||
load:plugin("user/package")
|
||||
load:cmd("LoadDependent")
|
||||
end
|
||||
}
|
||||
<
|
||||
If we were to call the command `:LoadDependent` it would first load
|
||||
'user/package', and then load 'user/dependent'.
|
||||
|
||||
==============================================================================
|
||||
7. Credits & License *dep-credits*
|
||||
|
||||
dep is licensed under the MIT License. Check the LICENSE file for more info.
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
@ -90,6 +90,9 @@ return function(opts)
|
||||
bench.setup()
|
||||
lazy.setup()
|
||||
|
||||
-- generate doc tags
|
||||
vim.cmd.helptags(vim.fn.stdpath('data')..'/site/pack/deps/opt/dep/doc')
|
||||
|
||||
local initialized, err = pcall(function()
|
||||
packager.set_base_dir(opts.base_dir or vim.fn.stdpath("data").."/site/pack/deps/opt/")
|
||||
bench.mark("load", function()
|
||||
@ -97,8 +100,7 @@ return function(opts)
|
||||
local root = packager:new({
|
||||
"squibid/dep",
|
||||
url = "https://git.squi.bid/squibid/dep.git",
|
||||
branch = "lazy",
|
||||
pin = true
|
||||
branch = "lazy"
|
||||
})
|
||||
if not root then
|
||||
logger:log("error", "couldn't register root package")
|
||||
|
@ -1,10 +1,12 @@
|
||||
local logger = require('dep.log')
|
||||
local packager = require('dep.package')
|
||||
|
||||
---@class lazy_loader
|
||||
---@field load function the function to load the plugin
|
||||
---@field command_ids table the commands that have been registered
|
||||
---@field auto_ids table the auto commands that have been registered
|
||||
---@field keybind_ids table the keybinds that have been registered
|
||||
---@field command_ids string[] the commands that have been registered
|
||||
---@field auto_ids number[] the auto commands that have been registered
|
||||
---@field keybind_ids table[] the keybinds that have been registered
|
||||
---@field plugin_ids table[] the plugins that have been registered
|
||||
local lazy_loader = {}
|
||||
|
||||
--- create a new instance of lazy
|
||||
@ -16,6 +18,7 @@ function lazy_loader:new()
|
||||
o.command_ids = {}
|
||||
o.auto_ids = {}
|
||||
o.keybind_ids = {}
|
||||
o.plugin_ids = {}
|
||||
|
||||
self.__index = self
|
||||
|
||||
@ -33,8 +36,32 @@ end
|
||||
---@param opts vim.api.keyset.user_command? options
|
||||
function lazy_loader:cmd(name, opts)
|
||||
opts = opts or {}
|
||||
vim.api.nvim_create_user_command(name, opts['callback'] or function()
|
||||
|
||||
-- move the rerun arg to a seperate variable because keymap.set doesn't like
|
||||
-- options it doesn't know of
|
||||
local rerun = opts["rerun"] or true
|
||||
opts['rerun'] = nil
|
||||
|
||||
-- load the plugin on completion
|
||||
if not opts["complete"] then
|
||||
opts["complete"] = function(_, line, _)
|
||||
self:cleanup()
|
||||
|
||||
-- return all completions for the current input, we need this to ensure
|
||||
-- that the new completions are loaded from the actual plugin, not our
|
||||
-- definiton of the command
|
||||
return vim.fn.getcompletion(line, "cmdline")
|
||||
end
|
||||
opts["nargs"] = "*"
|
||||
end
|
||||
|
||||
vim.api.nvim_create_user_command(name, opts['callback'] or function(_)
|
||||
self:cleanup()
|
||||
|
||||
-- attempt to rerun the command
|
||||
if not rerun then
|
||||
pcall(vim.cmd, name)
|
||||
end
|
||||
end, opts)
|
||||
|
||||
table.insert(self.command_ids, name)
|
||||
@ -57,7 +84,7 @@ end
|
||||
--- create an auto command which will trigger on filetype
|
||||
---@param filetype string filetype to register the auto on
|
||||
function lazy_loader:ft(filetype)
|
||||
lazy_loader:auto("FileType", {
|
||||
self:auto("FileType", {
|
||||
pattern = filetype
|
||||
})
|
||||
end
|
||||
@ -93,29 +120,53 @@ function lazy_loader:keymap(mode, bind, opts)
|
||||
table.insert(self.keybind_ids, { ['mode'] = mode, ['bind'] = bind })
|
||||
end
|
||||
|
||||
--- load a plugin when another plugin loads
|
||||
---@param plugin string plugin name
|
||||
---@param opts table? options
|
||||
function lazy_loader:plugin(plugin, opts)
|
||||
opts = opts or {}
|
||||
opts["callback"] = opts["callback"] or function()
|
||||
self:cleanup()
|
||||
end
|
||||
|
||||
if packager.get_packages()[plugin].loaded then
|
||||
opts["callback"]()
|
||||
else
|
||||
local on_load = packager.get_packages()[plugin].on_load
|
||||
local on_load_idx = #on_load + 1
|
||||
on_load[on_load_idx] = opts["callback"]
|
||||
|
||||
table.insert(self.plugin_ids, { plugin, on_load_idx })
|
||||
end
|
||||
end
|
||||
|
||||
--- cleanup all the callbacks, and load the plugin
|
||||
function lazy_loader:cleanup()
|
||||
-- cleanup user commands
|
||||
for _, command_id in pairs(self.command_ids) do
|
||||
for _, command_id in ipairs(self.command_ids) do
|
||||
local ok, err = pcall(vim.api.nvim_del_user_command, command_id)
|
||||
if not ok then
|
||||
logger:log("lazy", err or "failed to delete user command")
|
||||
end
|
||||
end
|
||||
-- cleanup auto commands
|
||||
for _, auto_id in pairs(self.auto_ids) do
|
||||
for _, auto_id in ipairs(self.auto_ids) do
|
||||
local ok, err = pcall(vim.api.nvim_del_autocmd, auto_id)
|
||||
if not ok then
|
||||
logger:log("lazy", err or "failed to delete auto command")
|
||||
end
|
||||
end
|
||||
-- cleanup keymaps
|
||||
for _, keybind_id in pairs(self.keybind_ids) do
|
||||
for _, keybind_id in ipairs(self.keybind_ids) do
|
||||
local ok, err = pcall(vim.keymap.del, keybind_id.mode, keybind_id.bind, {})
|
||||
if not ok then
|
||||
logger:log("lazy", err or "failed to delete keymap")
|
||||
end
|
||||
end
|
||||
-- cleanup plugins
|
||||
for _, plugin_id in ipairs(self.plugin_ids) do
|
||||
table.remove(packager.get_packages()[plugin_id[1]].on_load, plugin_id[2])
|
||||
end
|
||||
-- load the plugin
|
||||
self:load()
|
||||
end
|
||||
|
@ -59,4 +59,14 @@ function short.keymap(mode, bind, opts)
|
||||
end
|
||||
end
|
||||
|
||||
--- create a single plugin load event for when another plugin loads
|
||||
---@param plugin string plugin name
|
||||
---@param opts table? options
|
||||
---@return function callback
|
||||
function short.plugin(plugin, opts)
|
||||
return function(load)
|
||||
load:plugin(plugin, opts)
|
||||
end
|
||||
end
|
||||
|
||||
return short
|
||||
|
@ -30,10 +30,7 @@ function modules:setup(speclist, overrides, config_path)
|
||||
"lua", (speclist.modules.prefix:gsub("%.", "/"))
|
||||
)
|
||||
|
||||
h.uv.fs_scandir(path, function(err, handle)
|
||||
if err then
|
||||
logger:log("error", "failed to load modules; reason: %s", err)
|
||||
else
|
||||
local handle = h.uv.fs_scandir(path)
|
||||
while handle do
|
||||
local name = h.uv.fs_scandir_next(handle)
|
||||
if name then
|
||||
@ -46,13 +43,9 @@ function modules:setup(speclist, overrides, config_path)
|
||||
-- when attempting to load it
|
||||
name = name:sub(0, #name - 4)
|
||||
|
||||
-- attempt to load the module
|
||||
local mod = module.new(nil, name, speclist.modules.prefix, overrides)
|
||||
if not mod then
|
||||
goto continue
|
||||
end
|
||||
-- put the module into the list of modules
|
||||
table.insert(speclist.modules, name)
|
||||
|
||||
table.insert(o.modules, mod)
|
||||
::continue::
|
||||
elseif name == nil then
|
||||
-- no more entries
|
||||
@ -60,12 +53,11 @@ function modules:setup(speclist, overrides, config_path)
|
||||
else
|
||||
-- if there's a single error bail out
|
||||
logger:log("error", "failed to run clean uv.fs_scandir_next failed")
|
||||
return
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
else
|
||||
|
||||
-- loop through all modules and initialize them
|
||||
for _, modpath in ipairs(speclist.modules) do
|
||||
local mod = module.new(nil, modpath, speclist.modules.prefix, overrides)
|
||||
@ -76,7 +68,6 @@ function modules:setup(speclist, overrides, config_path)
|
||||
table.insert(o.modules, mod)
|
||||
::continue::
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
@ -165,18 +165,10 @@ function package:new(spec, overrides)
|
||||
-- if the child package is lazy loaded make sure the child package
|
||||
-- is only loaded when the parent package has finished loading
|
||||
if o.lazy then
|
||||
table.insert(o.on_load, function()
|
||||
local ok = o:loadtree(true)
|
||||
if not ok then
|
||||
logger:log("lazy",
|
||||
"failed to run loadtree for %s, some packages may not be loaded",
|
||||
o.id)
|
||||
end
|
||||
end)
|
||||
|
||||
-- tell the dep that it's gonna be lazy
|
||||
pkg.lazy = true
|
||||
table.insert(pkg.lazy_load, function(_) end)
|
||||
table.insert(pkg.lazy_load,
|
||||
require("dep.lazy.loader.short").plugin(id))
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -252,6 +244,10 @@ function package:ensureadded(force)
|
||||
--- load a package
|
||||
---@param pkg package
|
||||
local function loadpkg(pkg)
|
||||
if not self.enabled then
|
||||
return false
|
||||
end
|
||||
|
||||
-- make sure to load the dependencies first
|
||||
for _, p in pairs(pkg.requirements) do
|
||||
if not p.loaded then
|
||||
@ -316,7 +312,7 @@ function package:ensureadded(force)
|
||||
if load_cond ~= true then
|
||||
local ok, err = pcall(load_cond, l)
|
||||
if not ok then
|
||||
logger:log("lazy", "failed to register load conditions for '%s': %s",
|
||||
logger:log("error", "failed to register lazy load conditions for '%s': %s",
|
||||
self.name, err)
|
||||
end
|
||||
end
|
||||
|
@ -20,16 +20,29 @@ end
|
||||
---@param log_line string log line
|
||||
---@return chunk[] chunks
|
||||
function format.log_line(log_line)
|
||||
local log_time = string.sub( log_line, string.find(log_line, "%[") + 1,
|
||||
-- make sure we don't do operations on nil values
|
||||
if not log_line or log_line == "" then
|
||||
return {}
|
||||
end
|
||||
|
||||
-- error on any nil values, this should prevent us from parsing an incorrectly
|
||||
-- formatted log line
|
||||
local log_time, colon, log_path, log_path_ln, level, rest
|
||||
local ok = pcall(function()
|
||||
log_time = string.sub(log_line, string.find(log_line, "%[") + 1,
|
||||
string.find(log_line, "%]") - 1)
|
||||
local colon = string.find(log_line, ":", 11)
|
||||
local log_path = string.sub(log_line, string.find(log_line, "%]") + 2,
|
||||
colon = string.find(log_line, ":", 11)
|
||||
log_path = string.sub(log_line, string.find(log_line, "%]") + 2,
|
||||
colon - 1)
|
||||
local log_path_ln = string.sub(log_line, colon + 1,
|
||||
log_path_ln = string.sub(log_line, colon + 1,
|
||||
string.find(log_line, ":", colon + 1) - 1)
|
||||
local level = string.sub(log_line, string.find(log_line, "%(") + 1,
|
||||
level = string.sub(log_line, string.find(log_line, "%(") + 1,
|
||||
string.find(log_line, "%)") - 1)
|
||||
local rest = string.sub(log_line, string.find(log_line, "%)") + 2)
|
||||
rest = string.sub(log_line, string.find(log_line, "%)") + 2)
|
||||
end)
|
||||
if not ok then
|
||||
return {}
|
||||
end
|
||||
|
||||
return {
|
||||
{ "[", "" },
|
||||
|
@ -44,8 +44,10 @@ local function page_log()
|
||||
|
||||
-- put the cursor at the bottom of the page after drawing
|
||||
p.post_draw = function()
|
||||
if ui.winnr then
|
||||
vim.api.nvim_win_set_cursor(ui.winnr, { #p.content, 0 })
|
||||
end
|
||||
end
|
||||
|
||||
-- read in the contents of the file, and keep watching for updates
|
||||
local function update_contents()
|
||||
|
63
tests/dep_spec.lua
Normal file
63
tests/dep_spec.lua
Normal file
@ -0,0 +1,63 @@
|
||||
---@diagnostic disable: undefined-global, undefined-field
|
||||
local dep_ui_format = require("dep.ui.format")
|
||||
local dep_spec_man = require("dep.spec")
|
||||
|
||||
describe("ui log formatting", function()
|
||||
it("returns the proper chunks to print a formatted line", function()
|
||||
assert.same(
|
||||
{
|
||||
{ "[", "" },
|
||||
{ "11:22:33", "Boolean" },
|
||||
{ "] ", "" },
|
||||
{ "file.lua", "String" },
|
||||
{ ":", "" },
|
||||
{ "1", "Number" },
|
||||
{ ": ", "" },
|
||||
{ "some fancy message", "" }
|
||||
},
|
||||
dep_ui_format.log_line("[11:22:33] file.lua:1:(vim) some fancy message")
|
||||
)
|
||||
|
||||
-- malformed log line
|
||||
assert.same({},
|
||||
dep_ui_format.log_line("11:22:33] file.lua:1:(vim) some fancy message"))
|
||||
|
||||
-- test nil values
|
||||
assert.same({}, dep_ui_format.log_line(""))
|
||||
assert.same({}, dep_ui_format.log_line(nil))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("package specification", function()
|
||||
it("gets the package's name", function()
|
||||
assert.equal(dep_spec_man.get_name({ "user/package" }), "package")
|
||||
assert.equal(dep_spec_man.get_name({ "user/package.git" }), "package.git")
|
||||
end)
|
||||
|
||||
it("ensurses specs are in the proper format", function()
|
||||
local correct = { "user/package" }
|
||||
assert.same(dep_spec_man.correct_spec("user/package"), correct)
|
||||
assert.same(dep_spec_man.correct_spec({ "user/package" }), correct)
|
||||
assert.same(dep_spec_man.correct_spec({ { "user/package" } }), correct)
|
||||
end)
|
||||
|
||||
it("checks a spec for correctness", function()
|
||||
assert.same(
|
||||
dep_spec_man.check({ "user/package" }, true),
|
||||
{ "user/package" }
|
||||
)
|
||||
|
||||
assert.same(
|
||||
dep_spec_man.check({
|
||||
"user/package",
|
||||
deps = "user/dependency"
|
||||
}, true),
|
||||
{
|
||||
"user/package",
|
||||
deps = {
|
||||
"user/dependency"
|
||||
}
|
||||
}
|
||||
)
|
||||
end)
|
||||
end)
|
1
tests/minit.lua
Normal file
1
tests/minit.lua
Normal file
@ -0,0 +1 @@
|
||||
vim.opt.rtp:prepend(".")
|
Reference in New Issue
Block a user