*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| - Lazy Loading |dep-examples-lazy-loading| 5. Commands |dep-commands| 6. Examples |dep-examples| - Declaring Dependencies |dep-examples-declaring-dependencies| - Modules |dep-examples-modules| 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() end }) < If you wish the second argument may be completely ommitted. ------------------------------------------------------------------------------ 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", "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", "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: