From ecb95923c4dd68ed5cce15eee14a770ee24333b9 Mon Sep 17 00:00:00 2001 From: phosphene47 Date: Wed, 17 Nov 2021 21:16:50 +1100 Subject: Create readme and add license --- README.md | 404 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 404 insertions(+) create mode 100644 README.md (limited to 'README.md') diff --git a/README.md b/README.md new file mode 100644 index 0000000..e5995e8 --- /dev/null +++ b/README.md @@ -0,0 +1,404 @@ +# dep + +> This readme is a work in progress. + +A versatile, declarative and correct +[neovim](https://neovim.io/) package manager in [lua](https://www.lua.org/). +Written for personal use by [phosphene47](https://github.com/phosphene47). + +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. + +## Requirements + +- [neovim](https://neovim.io/) 0.5+ +- [git](https://git-scm.com/) + +## Setup + +1. Create `lua/bootstrap.lua` in your neovim config directory. + +```lua +-- ~/.config/nvim/lua/bootstrap.lua: +-- automatically install `chiyadev/dep` on startup +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://github.com/chiyadev/dep", path }) +end + +vim.cmd("packadd dep") +``` + +2. In `init.lua`, call `dep` with an array of package specifications. + +```lua +require "bootstrap" +require "dep" { + -- list of package specs... +} +``` + +## Commands + +- `:DepSync` - installs new packages, updates packages to the latest versions, + cleans removed packages and reloads packages as necessary. +- `:DepClean` - cleans removed packages. +- `:DepReload` - reloads all packages. +- `:DepList` - prints the package list, performance metrics and dependency graphs. +- `:DepLog` - opens the log file. +- `:DepConfig` - opens the file that called dep, for convenience. + +## Package specification + +A package must be declared in the following format. + +```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 after the package is loaded into neovim. + function() + require "package".setup(...) + end, + + -- [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 installed or updated. + config = function() + os.execute(...) + 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.chiya.dev/user/package.git", + + -- [string] Overrides the name of the branch to clone. + -- Defaults to whatever the remote configured as their HEAD, which is usually "master". + branch = "develop", + + -- [boolean] Prevents the package from being loaded. + disable = true, + + -- [boolean] Prevents the package from being updated. + pin = true, + + -- [string|array] Specifies dependencies that must be loaded before the package. + -- If given a string, it is wrapped into an array. + requires = {...}, + + -- [string|array] Specifies dependents that must be loaded after the package. + -- If given a string, it is wrapped into an array. + deps = {...} +} +``` + +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", + requires = "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", + requires = { "user/dependency", "user/another_dependency" }, + deps = "user/dependent", + disabled = true, + config = function() + print "my config hook" + os.execute("make") + end + } +} +``` + +## 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", + requires = { + { + "user/dependency1", + requires = "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", + requires = "user/dependency2", + deps = "user/package" + } +} + +-- which is equivalent to +require "dep" { + { + "user/dependency1", + requires = "user/dependency2" + }, + { + "user/package", + requires = "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", + requires = "user/package2" + }, + { + "user/package2", + requires = "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 + requires = "user/dependency" + }, + { + "user/package2", + disabled = true, -- implied + requires = "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", + function() + error("bad hook") + end + }, + { + "user/dependent", + requires = "user/problematic", + function() + print "unreachable" + end + } +} +``` + +## Separating code into modules + +Suppose you split your `init.lua` into two files `packages/search.lua` and +`packages/vcs.lua`, which declare the packages +[telescope.nvim](https://github.com/nvim-telescope/telescope.nvim) and +[vim-fugitive](https://github.com/tpope/vim-fugitive) respectively. + +```lua +-- ~/.config/nvim/lua/packages/search.lua: +return { + { + "nvim-telescope/telescope.nvim", + requires = "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.", + "search", + "vcs" + } +} + +-- the above is equivalent to +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", + requires = "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 + requires = { + { + "user/dependency", + -- disabled = true -- not implied + } + }, + deps = { + { + "user/dependent", + disabled = true -- implied by dependency + } + } + } +} +``` + +## Miscellaneous configuration + +dep accepts configuration parameters as named fields in the package list. + +```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. + modules = { + -- [string] Prefix string to prepend to all module names. + prefix = "", + }, + + -- list of package specs... +} +``` + +## License + +dep is licensed under the [MIT License](LICENSE). -- cgit v1.2.1