Compare commits

...

21 Commits

Author SHA1 Message Date
70853bd01e disabled packages were still getting force loaded 2025-07-10 21:20:53 -04:00
9d4322572c should've tested the changes, nvim_create_usercommand doesn't like...
unkown options
2025-07-04 05:27:36 -04:00
3b33a604d8 commands get rerun by default now 2025-07-04 05:25:06 -04:00
5aff147731 add better type definitions, and fix a bug related to...
lua indexing my beloved
2025-07-04 05:04:23 -04:00
edf32fbf06 fix bug: remove the callback from the on_load list 2025-07-03 18:02:44 -04:00
adec93b7f4 fix formatting log lines causing errors 2025-07-03 17:02:33 -04:00
1cd5f63f8e actually error when we fail to setup lazy loading for a package 2025-07-03 17:00:46 -04:00
8e46eddecd Allow users to lazy load on another package 2025-07-03 16:31:04 -04:00
542298c1fe registering a filetype lazy load condition should happen on self not the...
lazy_loader
2025-07-02 21:51:34 -04:00
cfc3f08d53 remove a testcase for specs 2025-07-02 21:13:30 -04:00
1c2f49fcfa unpin dep internally 2025-07-02 21:13:08 -04:00
f6209048f1 Revert "use the correct_spec function to handle dependencies and requirements"
This reverts commit 318a86d786.
2025-07-02 21:07:04 -04:00
5bd30d9397 don't error when the ui is closed 2025-07-02 20:36:14 -04:00
1538046b6f make finding modules synchronous to avoid some bugs when calling...
internal neovim api functions
2025-07-02 20:34:42 -04:00
5deffca36e improve lazy loading on commands, dep will now load on completion 2025-07-02 17:54:43 -04:00
318a86d786 use the correct_spec function to handle dependencies and requirements 2025-07-02 15:00:37 -04:00
5541a656e2 add tests for the spec checker 2025-07-02 15:00:00 -04:00
59a963a5c5 update the LICENSE 2025-07-02 04:23:14 -04:00
cd43b3b853 add git pre-commit hooks 2025-07-02 04:15:58 -04:00
585f04c745 add testing...
this is very limited right now, but I will expand as I see fit
2025-07-02 03:53:31 -04:00
a13d616da5 add documentation 2025-07-02 03:11:20 -04:00
15 changed files with 900 additions and 77 deletions

11
.githooks/pre-commit Executable file
View 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
View File

@ -1 +1,2 @@
.DS_Store
doc/tags

View File

@ -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
View File

@ -0,0 +1,4 @@
test:
nvim --headless -c "PlenaryBustedDirectory tests/ {minimal_init = './tests/minit.lua'}"
.PHONY: test

View File

@ -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
View 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:

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {
{ "[", "" },

View File

@ -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
View 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
View File

@ -0,0 +1 @@
vim.opt.rtp:prepend(".")