diff --git a/lua/lvim/bootstrap.lua b/lua/lvim/bootstrap.lua index 5385e8a8..a2a97cea 100644 --- a/lua/lvim/bootstrap.lua +++ b/lua/lvim/bootstrap.lua @@ -3,6 +3,7 @@ local M = {} if vim.fn.has "nvim-0.8" ~= 1 then vim.notify("Please upgrade your Neovim base installation. Lunarvim requires v0.8+", vim.log.levels.WARN) vim.wait(5000, function() + ---@diagnostic disable-next-line: redundant-return-value return false end) vim.cmd "cquit" @@ -23,7 +24,7 @@ _G.require_safe = require("lvim.utils.modules").require_safe _G.reload = require("lvim.utils.modules").reload ---Get the full path to `$LUNARVIM_RUNTIME_DIR` ----@return string +---@return string|nil function _G.get_runtime_dir() local lvim_runtime_dir = os.getenv "LUNARVIM_RUNTIME_DIR" if not lvim_runtime_dir then @@ -34,7 +35,7 @@ function _G.get_runtime_dir() end ---Get the full path to `$LUNARVIM_CONFIG_DIR` ----@return string +---@return string|nil function _G.get_config_dir() local lvim_config_dir = os.getenv "LUNARVIM_CONFIG_DIR" if not lvim_config_dir then @@ -44,7 +45,7 @@ function _G.get_config_dir() end ---Get the full path to `$LUNARVIM_CACHE_DIR` ----@return string +---@return string|nil function _G.get_cache_dir() local lvim_cache_dir = os.getenv "LUNARVIM_CACHE_DIR" if not lvim_cache_dir then @@ -60,11 +61,11 @@ function M:init(base_dir) self.config_dir = get_config_dir() self.cache_dir = get_cache_dir() self.pack_dir = join_paths(self.runtime_dir, "site", "pack") - self.packer_install_dir = join_paths(self.runtime_dir, "site", "pack", "packer", "start", "packer.nvim") - self.packer_cache_path = join_paths(self.config_dir, "plugin", "packer_compiled.lua") + self.lazy_install_dir = join_paths(self.pack_dir, "lazy", "opt", "lazy.nvim") ---@meta overridden to use LUNARVIM_CACHE_DIR instead, since a lot of plugins call this function internally ---NOTE: changes to "data" are currently unstable, see #2507 + ---@diagnostic disable-next-line: duplicate-set-field vim.fn.stdpath = function(what) if what == "cache" then return _G.get_cache_dir() @@ -79,10 +80,9 @@ function M:init(base_dir) end if os.getenv "LUNARVIM_RUNTIME_DIR" then - -- vim.opt.rtp:append(os.getenv "LUNARVIM_RUNTIME_DIR" .. path_sep .. "lvim") vim.opt.rtp:remove(join_paths(vim.call("stdpath", "data"), "site")) vim.opt.rtp:remove(join_paths(vim.call("stdpath", "data"), "site", "after")) - vim.opt.rtp:prepend(join_paths(self.runtime_dir, "site")) + -- vim.opt.rtp:prepend(join_paths(self.runtime_dir, "site")) vim.opt.rtp:append(join_paths(self.runtime_dir, "lvim", "after")) vim.opt.rtp:append(join_paths(self.runtime_dir, "site", "after")) @@ -90,22 +90,17 @@ function M:init(base_dir) vim.opt.rtp:remove(join_paths(vim.call("stdpath", "config"), "after")) vim.opt.rtp:prepend(self.config_dir) vim.opt.rtp:append(join_paths(self.config_dir, "after")) - -- TODO: we need something like this: vim.opt.packpath = vim.opt.rtp - vim.cmd [[let &packpath = &runtimepath]] + vim.opt.packpath = vim.opt.rtp:get() end - if not vim.env.LVIM_TEST_ENV then - require "lvim.impatient" - end - - require("lvim.config"):init() - require("lvim.plugin-loader").init { package_root = self.pack_dir, - install_path = self.packer_install_dir, + install_path = self.lazy_install_dir, } + require("lvim.config"):init() + require("lvim.core.mason").bootstrap() return self diff --git a/lua/lvim/config/_deprecated.lua b/lua/lvim/config/_deprecated.lua index 4cf4381e..d4b15f30 100644 --- a/lua/lvim/config/_deprecated.lua +++ b/lua/lvim/config/_deprecated.lua @@ -41,6 +41,24 @@ function M.handle() end, }) + ---@deprecated + lvim.builtin.dashboard = {} + setmetatable(lvim.builtin.dashboard, { + __newindex = function(_, k, _) + deprecate("lvim.builtin.dashboard." .. k, "Use `lvim.builtin.alpha` instead. See LunarVim#1906") + end, + }) + + ---@deprecated + lvim.lsp.popup_border = {} + setmetatable(lvim.lsp.popup_border, mt) + + ---@deprecated + lvim.lang = {} + setmetatable(lvim.lang, mt) +end + +function M.post_load() if lvim.lsp.override and not vim.tbl_isempty(lvim.lsp.override) then deprecate("lvim.lsp.override", "Use `lvim.lsp.automatic_configuration.skipped_servers` instead") vim.tbl_map(function(c) @@ -64,21 +82,78 @@ function M.handle() ) end - ---@deprecated - lvim.builtin.dashboard = {} - setmetatable(lvim.builtin.dashboard, { - __newindex = function(_, k, _) - deprecate("lvim.builtin.dashboard." .. k, "Use `lvim.builtin.alpha` instead. See LunarVim#1906") - end, - }) + local function convert_spec_to_lazy(spec) + local alternatives = { + setup = "init", + as = "name", + opt = "lazy", + run = "build", + lock = "pin", + tag = "version", + } - ---@deprecated - lvim.lsp.popup_border = {} - setmetatable(lvim.lsp.popup_border, mt) + alternatives.requires = function() + if type(spec.requires) == "string" then + spec.dependencies = { spec.requires } + else + spec.dependencies = spec.requires + end - ---@deprecated - lvim.lang = {} - setmetatable(lvim.lang, mt) + return "Use `dependencies` instead" + end + + alternatives.disable = function() + if type(spec.disabled) == "function" then + spec.enabled = function() + return not spec.disabled() + end + else + spec.enabled = not spec.disabled + end + return "Use `enabled` instead" + end + + alternatives.wants = function() + return "It's not needed in most cases, otherwise use `dependencies`." + end + alternatives.needs = alternatives.wants + + alternatives.module = function() + spec.lazy = true + return "Use `lazy = true` instead." + end + + for old_key, alternative in pairs(alternatives) do + if spec[old_key] ~= nil then + local message + + if type(alternative) == "function" then + message = alternative() + else + spec[alternative] = spec[old_key] + end + spec[old_key] = nil + + message = message or string.format("Use `%s` instead.", alternative) + deprecate( + string.format("%s` in `lvim.plugins", old_key), + message .. " See https://github.com/folke/lazy.nvim#-migration-guide" + ) + end + end + + if spec[1] and spec[1]:match "^http" then + spec.url = spec[1] + spec[1] = nil + deprecate("{ 'http...' }` in `lvim.plugins", "Use { url = 'http...' } instead.") + end + end + + for _, plugin in ipairs(lvim.plugins) do + if type(plugin) == "table" then + convert_spec_to_lazy(plugin) + end + end end return M diff --git a/lua/lvim/config/init.lua b/lua/lvim/config/init.lua index d15d5108..20fad32a 100644 --- a/lua/lvim/config/init.lua +++ b/lua/lvim/config/init.lua @@ -63,6 +63,8 @@ function M:load(config_path) Log:set_level(lvim.log.level) + require("lvim.config._deprecated").post_load() + autocmds.define_autocmds(lvim.autocommands) vim.g.mapleader = (lvim.leader == "space" and " ") or lvim.leader diff --git a/lua/lvim/core/breadcrumbs.lua b/lua/lvim/core/breadcrumbs.lua index 3dfd7bab..b2355684 100644 --- a/lua/lvim/core/breadcrumbs.lua +++ b/lua/lvim/core/breadcrumbs.lua @@ -12,7 +12,7 @@ M.config = function() "help", "startify", "dashboard", - "packer", + "lazy", "neo-tree", "neogitstatus", "NvimTree", diff --git a/lua/lvim/core/bufferline.lua b/lua/lvim/core/bufferline.lua index b6acadec..1344eb9a 100644 --- a/lua/lvim/core/bufferline.lua +++ b/lua/lvim/core/bufferline.lua @@ -117,8 +117,8 @@ M.config = function() highlight = "PanelHeading", }, { - filetype = "packer", - text = "Packer", + filetype = "lazy", + text = "Lazy", highlight = "PanelHeading", padding = 1, }, diff --git a/lua/lvim/core/illuminate.lua b/lua/lvim/core/illuminate.lua index 808ce724..5968b4bb 100644 --- a/lua/lvim/core/illuminate.lua +++ b/lua/lvim/core/illuminate.lua @@ -23,7 +23,7 @@ M.config = function() "fugitive", "alpha", "NvimTree", - "packer", + "lazy", "neogitstatus", "Trouble", "lir", diff --git a/lua/lvim/core/indentlines.lua b/lua/lvim/core/indentlines.lua index dc4a72ba..605a77d1 100644 --- a/lua/lvim/core/indentlines.lua +++ b/lua/lvim/core/indentlines.lua @@ -11,7 +11,7 @@ M.config = function() "help", "startify", "dashboard", - "packer", + "lazy", "neogitstatus", "NvimTree", "Trouble", diff --git a/lua/lvim/core/log.lua b/lua/lvim/core/log.lua index f4ff114a..d3acbf7f 100644 --- a/lua/lvim/core/log.lua +++ b/lua/lvim/core/log.lua @@ -21,13 +21,6 @@ function Log:set_level(level) s.level = log_level end end - - local packer_ok, _ = xpcall(function() - require("packer.log").cfg { log = { level = level } } - end, debug.traceback) - if not packer_ok then - vim.notify_once("Unable to set packer's log level to " .. level) - end end function Log:init() diff --git a/lua/lvim/core/nvimtree.lua b/lua/lvim/core/nvimtree.lua index 5653b35a..6f87e30d 100644 --- a/lua/lvim/core/nvimtree.lua +++ b/lua/lvim/core/nvimtree.lua @@ -185,7 +185,7 @@ function M.config() picker = "default", chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", exclude = { - filetype = { "notify", "packer", "qf", "diff", "fugitive", "fugitiveblame" }, + filetype = { "notify", "lazy", "qf", "diff", "fugitive", "fugitiveblame" }, buftype = { "nofile", "terminal", "help" }, }, }, diff --git a/lua/lvim/core/which-key.lua b/lua/lvim/core/which-key.lua index d1585702..ba816b2f 100644 --- a/lua/lvim/core/which-key.lua +++ b/lua/lvim/core/which-key.lua @@ -156,13 +156,15 @@ M.config = function() U = { "lua require'dapui'.toggle({reset = true})", "Toggle UI" }, }, p = { - name = "Packer", - c = { "PackerCompile", "Compile" }, - i = { "PackerInstall", "Install" }, - r = { "lua require('lvim.plugin-loader').recompile()", "Re-compile" }, - s = { "PackerSync", "Sync" }, - S = { "PackerStatus", "Status" }, - u = { "PackerUpdate", "Update" }, + name = "Plugins", + i = { "Lazy install", "Install" }, + s = { "Lazy sync", "Sync" }, + S = { "Lazy clear", "Status" }, + c = { "Lazy clean", "Clean" }, + u = { "Lazy update", "Update" }, + p = { "Lazy profile", "Profile" }, + l = { "Lazy log", "Log" }, + d = { "Lazy debug", "Debug" }, }, -- " Available Debug Adapters: @@ -268,11 +270,6 @@ M.config = function() "view neovim log", }, N = { "edit $NVIM_LOG_FILE", "Open the Neovim logfile" }, - p = { - "lua require('lvim.core.terminal').toggle_log_view(get_cache_dir() .. '/packer.nvim.log')", - "view packer log", - }, - P = { "edit $LUNARVIM_CACHE_DIR/packer.nvim.log", "Open the Packer logfile" }, }, r = { "LvimReload", "Reload LunarVim's configuration" }, u = { "LvimUpdate", "Update LunarVim" }, diff --git a/lua/lvim/impatient.lua b/lua/lvim/impatient.lua deleted file mode 100644 index beb3862a..00000000 --- a/lua/lvim/impatient.lua +++ /dev/null @@ -1,477 +0,0 @@ --- modified version from https://github.com/lewis6991/impatient.nvim -local vim = vim -local api = vim.api -local uv = vim.loop -local _loadfile = loadfile -local get_runtime = api.nvim__get_runtime -local fs_stat = uv.fs_stat -local mpack = vim.mpack -local loadlib = package.loadlib - -local std_cache = vim.fn.stdpath "cache" - -local sep -if jit.os == "Windows" then - sep = "\\" -else - sep = "/" -end - -local std_dirs = { - [""] = os.getenv "APPDIR", - [""] = os.getenv "VIMRUNTIME", - [""] = vim.fn.stdpath "data", - [""] = vim.fn.stdpath "config", - [""] = get_lvim_base_dir(), - [""] = get_runtime_dir(), - [""] = get_config_dir(), -} - -local function modpath_mangle(modpath) - for name, dir in pairs(std_dirs) do - modpath = modpath:gsub(dir, name) - end - return modpath -end - -local function modpath_unmangle(modpath) - for name, dir in pairs(std_dirs) do - modpath = modpath:gsub(name, dir) - end - return modpath -end - --- Overridable by user -local default_config = { - chunks = { - enable = true, - path = std_cache .. sep .. "luacache_chunks", - }, - modpaths = { - enable = true, - path = std_cache .. sep .. "luacache_modpaths", - }, -} - --- State used internally -local default_state = { - chunks = { - cache = {}, - profile = nil, - dirty = false, - get = function(self, path) - return self.cache[modpath_mangle(path)] - end, - set = function(self, path, chunk) - self.cache[modpath_mangle(path)] = chunk - end, - }, - modpaths = { - cache = {}, - profile = nil, - dirty = false, - get = function(self, mod) - if self.cache[mod] then - return modpath_unmangle(self.cache[mod]) - end - end, - set = function(self, mod, path) - self.cache[mod] = modpath_mangle(path) - end, - }, - log = {}, -} - ----@diagnostic disable-next-line: undefined-field -local M = vim.tbl_deep_extend("keep", _G.__luacache_config or {}, default_config, default_state) -_G.__luacache = M - -local function log(...) - M.log[#M.log + 1] = table.concat({ string.format(...) }, " ") -end - -local function print_log() - for _, l in ipairs(M.log) do - print(l) - end -end - -local function hash(modpath) - local stat = fs_stat(modpath) - if stat then - return stat.mtime.sec .. stat.mtime.nsec .. stat.size - end - error("Could not hash " .. modpath) -end - -local function profile(m, entry, name, loader) - if m.profile then - local mp = m.profile - mp[entry] = mp[entry] or {} - if not mp[entry].loader and loader then - mp[entry].loader = loader - end - if not mp[entry][name] then - mp[entry][name] = uv.hrtime() - end - end -end - -local function mprofile(mod, name, loader) - profile(M.modpaths, mod, name, loader) -end - -local function cprofile(path, name, loader) - if M.chunks.profile then - path = modpath_mangle(path) - end - profile(M.chunks, path, name, loader) -end - -function M.enable_profile() - local P = require "lvim.impatient.profile" - - M.chunks.profile = {} - M.modpaths.profile = {} - - loadlib = function(path, fun) - cprofile(path, "load_start") - local f, err = package.loadlib(path, fun) - cprofile(path, "load_end", "standard") - return f, err - end - - P.setup(M.modpaths.profile) - - api.nvim_create_user_command("LuaCacheProfile", function() - P.print_profile(M, std_dirs) - end, {}) -end - -local function get_runtime_file_from_parent(basename, paths) - -- Look in the cache to see if we have already loaded a parent module. - -- If we have then try looking in the parents directory first. - local parents = vim.split(basename, sep) - for i = #parents, 1, -1 do - local parent = table.concat(vim.list_slice(parents, 1, i), sep) - local ppath = M.modpaths:get(parent) - if ppath then - if ppath:sub(-9) == (sep .. "init.lua") then - ppath = ppath:sub(1, -10) -- a/b/init.lua -> a/b - else - ppath = ppath:sub(1, -5) -- a/b.lua -> a/b - end - - for _, path in ipairs(paths) do - -- path should be of form 'a/b/c.lua' or 'a/b/c/init.lua' - local modpath = ppath .. sep .. path:sub(#("lua" .. sep .. parent) + 2) - if fs_stat(modpath) then - return modpath, "cache(p)" - end - end - end - end -end - -local rtp = vim.split(vim.o.rtp, ",") - --- Make sure modpath is in rtp and that modpath is in paths. -local function validate_modpath(modpath, paths) - local match = false - for _, p in ipairs(paths) do - if vim.endswith(modpath, p) then - match = true - break - end - end - if not match then - return false - end - for _, dir in ipairs(rtp) do - if vim.startswith(modpath, dir) then - return fs_stat(modpath) ~= nil - end - end - return false -end - -local function get_runtime_file_cached(basename, paths) - local modpath, loader - local mp = M.modpaths - if mp.enable then - local modpath_cached = mp:get(basename) - if modpath_cached then - modpath, loader = modpath_cached, "cache" - else - modpath, loader = get_runtime_file_from_parent(basename, paths) - end - - if modpath and not validate_modpath(modpath, paths) then - modpath = nil - - -- Invalidate - mp.cache[basename] = nil - mp.dirty = true - end - end - - if not modpath then - -- What Neovim does by default; slowest - modpath, loader = get_runtime(paths, false, { is_lua = true })[1], "standard" - end - - if modpath then - mprofile(basename, "resolve_end", loader) - if mp.enable and loader ~= "cache" then - log("Creating cache for module %s", basename) - mp:set(basename, modpath) - mp.dirty = true - end - end - - return modpath -end - -local function extract_basename(pats) - local basename - - -- Deconstruct basename from pats - for _, pat in ipairs(pats) do - for i, npat in ipairs { - -- Ordered by most specific - "lua" - .. sep - .. "(.*)" - .. sep - .. "init%.lua", - "lua" .. sep .. "(.*)%.lua", - } do - local m = pat:match(npat) - if i == 2 and m and m:sub(-4) == "init" then - m = m:sub(0, -6) - end - if not basename then - if m then - basename = m - end - elseif m and m ~= basename then - -- matches are inconsistent - return - end - end - end - - return basename -end - -local function get_runtime_cached(pats, all, opts) - local fallback = false - if all or not opts or not opts.is_lua then - -- Fallback - fallback = true - end - - local basename - - if not fallback then - basename = extract_basename(pats) - end - - if fallback or not basename then - return get_runtime(pats, all, opts) - end - - return { get_runtime_file_cached(basename, pats) } -end - --- Copied from neovim/src/nvim/lua/vim.lua with two lines changed -local function load_package(name) - local basename = name:gsub("%.", sep) - local paths = { "lua" .. sep .. basename .. ".lua", "lua" .. sep .. basename .. sep .. "init.lua" } - - -- Original line: - -- local found = vim.api.nvim__get_runtime(paths, false, {is_lua=true}) - local found = { get_runtime_file_cached(basename, paths) } - if #found > 0 then - local f, err = loadfile(found[1]) - return f or error(err) - end - - local so_paths = {} - for _, trail in ipairs(vim._so_trails) do - local path = "lua" .. trail:gsub("?", basename) -- so_trails contains a leading slash - table.insert(so_paths, path) - end - - -- Original line: - -- found = vim.api.nvim__get_runtime(so_paths, false, {is_lua=true}) - found = { get_runtime_file_cached(basename, so_paths) } - if #found > 0 then - -- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is - -- a) strip prefix up to and including the first dash, if any - -- b) replace all dots by underscores - -- c) prepend "luaopen_" - -- So "foo-bar.baz" should result in "luaopen_bar_baz" - local dash = name:find("-", 1, true) - local modname = dash and name:sub(dash + 1) or name - local f, err = loadlib(found[1], "luaopen_" .. modname:gsub("%.", "_")) - return f or error(err) - end - return nil -end - -local function load_from_cache(path) - local mc = M.chunks - - local cache = mc:get(path) - - if not cache then - return nil, string.format("No cache for path %s", path) - end - - local mhash, codes = unpack(cache) - - if mhash ~= hash(path) then - mc:set(path) - mc.dirty = true - return nil, string.format("Stale cache for path %s", path) - end - - local chunk = loadstring(codes) - - if not chunk then - mc:set(path) - mc.dirty = true - return nil, string.format("Cache error for path %s", path) - end - - return chunk -end - -local function loadfile_cached(path) - cprofile(path, "load_start") - - local chunk, err - - if M.chunks.enable then - chunk, err = load_from_cache(path) - if chunk and not err then - log("Loaded cache for path %s", path) - cprofile(path, "load_end", "cache") - return chunk - end - log(err) - end - - chunk, err = _loadfile(path) - - if not err and M.chunks.enable then - log("Creating cache for path %s", path) - M.chunks:set(path, { hash(path), string.dump(chunk) }) - M.chunks.dirty = true - end - - cprofile(path, "load_end", "standard") - return chunk, err -end - -function M.save_cache() - local function _save_cache(t) - if not t.enable then - return - end - if t.dirty then - log("Updating chunk cache file: %s", t.path) - local f = assert(io.open(t.path, "w+b")) - f:write(mpack.encode(t.cache)) - f:flush() - t.dirty = false - end - end - _save_cache(M.chunks) - _save_cache(M.modpaths) -end - -local function clear_cache() - local function _clear_cache(t) - t.cache = {} - os.remove(t.path) - end - _clear_cache(M.chunks) - _clear_cache(M.modpaths) -end - -local function init_cache() - local function _init_cache(t) - if not t.enable then - return - end - if fs_stat(t.path) then - log("Loading cache file %s", t.path) - local f = assert(io.open(t.path, "rb")) - local ok - ok, t.cache = pcall(function() - return mpack.decode(f:read "*a") - end) - - if not ok then - log("Corrupted cache file, %s. Invalidating...", t.path) - os.remove(t.path) - t.cache = {} - end - t.dirty = not ok - end - end - - if not uv.fs_stat(std_cache) then - vim.fn.mkdir(std_cache, "p") - end - - _init_cache(M.chunks) - _init_cache(M.modpaths) -end - -local function setup() - init_cache() - - -- Usual package loaders - -- 1. package.preload - -- 2. vim._load_package - -- 3. package.path - -- 4. package.cpath - -- 5. all-in-one - - -- Override default functions - for i, loader in ipairs(package.loaders) do - if loader == vim._load_package then - package.loaders[i] = load_package - break - end - end - vim._load_package = load_package - - vim.api.nvim__get_runtime = get_runtime_cached - loadfile = loadfile_cached - - local augroup = api.nvim_create_augroup("impatient", {}) - - api.nvim_create_user_command("LuaCacheClear", clear_cache, {}) - api.nvim_create_user_command("LuaCacheLog", print_log, {}) - - api.nvim_create_autocmd({ "VimEnter", "VimLeave" }, { - group = augroup, - callback = M.save_cache, - }) - - api.nvim_create_autocmd("OptionSet", { - group = augroup, - pattern = "runtimepath", - callback = function() - rtp = vim.split(vim.o.rtp, ",") - end, - }) -end - -setup() - -return M diff --git a/lua/lvim/impatient/profile.lua b/lua/lvim/impatient/profile.lua deleted file mode 100644 index 2eafbbf2..00000000 --- a/lua/lvim/impatient/profile.lua +++ /dev/null @@ -1,253 +0,0 @@ -local M = {} - -local sep -if jit.os == "Windows" then - sep = "\\" -else - sep = "/" -end - -local api, uv = vim.api, vim.loop - -local function load_buffer(title, lines) - local bufnr = api.nvim_create_buf(false, false) - api.nvim_buf_set_lines(bufnr, 0, 0, false, lines) - api.nvim_buf_set_option(bufnr, "bufhidden", "wipe") - api.nvim_buf_set_option(bufnr, "buftype", "nofile") - api.nvim_buf_set_option(bufnr, "swapfile", false) - api.nvim_buf_set_option(bufnr, "modifiable", false) - api.nvim_buf_set_name(bufnr, title) - api.nvim_set_current_buf(bufnr) -end - -local function time_tostr(x) - if x == 0 then - return "?" - end - return string.format("%8.3fms", x) -end - -local function mem_tostr(x) - local unit = "" - for _, u in ipairs { "K", "M", "G" } do - if x < 1000 then - break - end - x = x / 1000 - unit = u - end - return string.format("%1.1f%s", x, unit) -end - -function M.print_profile(I, std_dirs) - local mod_profile = I.modpaths.profile - local chunk_profile = I.chunks.profile - - if not mod_profile and not chunk_profile then - print "Error: profiling was not enabled" - return - end - - local total_resolve = 0 - local total_load = 0 - local modules = {} - - for path, m in pairs(chunk_profile) do - m.load = m.load_end - m.load_start - m.load = m.load / 1000000 - m.path = path or "?" - end - - local module_content_width = 0 - - local unloaded = {} - - for module, m in pairs(mod_profile) do - local module_dot = module:gsub(sep, ".") - m.module = module_dot - - if not package.loaded[module_dot] and not package.loaded[module] then - unloaded[#unloaded + 1] = m - else - m.resolve = 0 - if m.resolve_start and m.resolve_end then - m.resolve = m.resolve_end - m.resolve_start - m.resolve = m.resolve / 1000000 - end - - m.loader = m.loader or m.loader_guess - - local path = I.modpaths.cache[module] - local path_prof = chunk_profile[path] - m.path = path or "?" - - if path_prof then - chunk_profile[path] = nil - m.load = path_prof.load - m.ploader = path_prof.loader - else - m.load = 0 - m.ploader = "NA" - end - - total_resolve = total_resolve + m.resolve - total_load = total_load + m.load - - if #module > module_content_width then - module_content_width = #module - end - - modules[#modules + 1] = m - end - end - - table.sort(modules, function(a, b) - return (a.resolve + a.load) > (b.resolve + b.load) - end) - - local paths = {} - - local total_paths_load = 0 - for _, m in pairs(chunk_profile) do - paths[#paths + 1] = m - total_paths_load = total_paths_load + m.load - end - - table.sort(paths, function(a, b) - return a.load > b.load - end) - - local lines = {} - local function add(fmt, ...) - local args = { ... } - for i, a in ipairs(args) do - if type(a) == "number" then - args[i] = time_tostr(a) - end - end - - lines[#lines + 1] = string.format(fmt, unpack(args)) - end - - local time_cell_width = 12 - local loader_cell_width = 11 - local time_content_width = time_cell_width - 2 - local loader_content_width = loader_cell_width - 2 - local module_cell_width = module_content_width + 2 - - local tcwl = string.rep("─", time_cell_width) - local lcwl = string.rep("─", loader_cell_width) - local mcwl = string.rep("─", module_cell_width + 2) - - local n = string.rep("─", 200) - - local module_cell_format = "%-" .. module_cell_width .. "s" - local loader_format = "%-" .. loader_content_width .. "s" - local line_format = "%s │ %s │ %s │ %s │ %s │ %s" - - local row_fmt = line_format:format( - " %" .. time_content_width .. "s", - loader_format, - "%" .. time_content_width .. "s", - loader_format, - module_cell_format, - "%s" - ) - - local title_fmt = line_format:format( - " %-" .. time_content_width .. "s", - loader_format, - "%-" .. time_content_width .. "s", - loader_format, - module_cell_format, - "%s" - ) - - local title1_width = time_cell_width + loader_cell_width - 1 - local title1_fmt = ("%s │ %s │"):format(" %-" .. title1_width .. "s", "%-" .. title1_width .. "s") - - add "Note: this report is not a measure of startup time. Only use this for comparing" - add "between cached and uncached loads of Lua modules" - add "" - - add "Cache files:" - for _, f in ipairs { I.chunks.path, I.modpaths.path } do - local size = vim.loop.fs_stat(f).size - add(" %s %s", f, mem_tostr(size)) - end - add "" - - add "Standard directories:" - for alias, path in pairs(std_dirs) do - add(" %-12s -> %s", alias, path) - end - add "" - - add("%s─%s┬%s─%s┐", tcwl, lcwl, tcwl, lcwl) - add(title1_fmt, "Resolve", "Load") - add("%s┬%s┼%s┬%s┼%s┬%s", tcwl, lcwl, tcwl, lcwl, mcwl, n) - add(title_fmt, "Time", "Method", "Time", "Method", "Module", "Path") - add("%s┼%s┼%s┼%s┼%s┼%s", tcwl, lcwl, tcwl, lcwl, mcwl, n) - add(row_fmt, total_resolve, "", total_load, "", "Total", "") - add("%s┼%s┼%s┼%s┼%s┼%s", tcwl, lcwl, tcwl, lcwl, mcwl, n) - for _, p in ipairs(modules) do - add(row_fmt, p.resolve, p.loader, p.load, p.ploader, p.module, p.path) - end - add("%s┴%s┴%s┴%s┴%s┴%s", tcwl, lcwl, tcwl, lcwl, mcwl, n) - - if #paths > 0 then - add "" - add(n) - local f3 = " %" .. time_content_width .. "s │ %" .. loader_content_width .. "s │ %s" - add "Files loaded with no associated module" - add("%s┬%s┬%s", tcwl, lcwl, n) - add(f3, "Time", "Loader", "Path") - add("%s┼%s┼%s", tcwl, lcwl, n) - add(f3, total_paths_load, "", "Total") - add("%s┼%s┼%s", tcwl, lcwl, n) - for _, p in ipairs(paths) do - add(f3, p.load, p.loader, p.path) - end - add("%s┴%s┴%s", tcwl, lcwl, n) - end - - if #unloaded > 0 then - add "" - add(n) - add "Modules which were unable to loaded" - add(n) - for _, p in ipairs(unloaded) do - lines[#lines + 1] = p.module - end - add(n) - end - - load_buffer("Impatient Profile Report", lines) -end - -M.setup = function(profile) - local _require = require - - require = function(mod) - local basename = mod:gsub("%.", sep) - if not profile[basename] then - profile[basename] = {} - profile[basename].resolve_start = uv.hrtime() - profile[basename].loader_guess = "" - end - return _require(mod) - end - - -- Add profiling around all the loaders - local pl = package.loaders - for i = 1, #pl do - local l = pl[i] - pl[i] = function(mod) - local basename = mod:gsub("%.", sep) - profile[basename].loader_guess = i == 1 and "preloader" or "loader #" .. i - return l(mod) - end - end -end - -return M diff --git a/lua/lvim/lsp/providers/sumneko_lua.lua b/lua/lvim/lsp/providers/sumneko_lua.lua index 7a309a7f..a73d3edc 100644 --- a/lua/lvim/lsp/providers/sumneko_lua.lua +++ b/lua/lvim/lsp/providers/sumneko_lua.lua @@ -53,7 +53,7 @@ local opts = { }, }, diagnostics = { - globals = { "vim", "lvim", "packer_plugins", "reload" }, + globals = { "vim", "lvim", "reload" }, }, workspace = default_workspace, }, diff --git a/lua/lvim/plugin-loader.lua b/lua/lvim/plugin-loader.lua index 4f1fe7c4..5949236c 100644 --- a/lua/lvim/plugin-loader.lua +++ b/lua/lvim/plugin-loader.lua @@ -3,128 +3,127 @@ local plugin_loader = {} local utils = require "lvim.utils" local Log = require "lvim.core.log" local join_paths = utils.join_paths -local in_headless = #vim.api.nvim_list_uis() == 0 --- we need to reuse this outside of init() -local compile_path = join_paths(get_config_dir(), "plugin", "packer_compiled.lua") -local snapshot_path = join_paths(get_cache_dir(), "snapshots") -local default_snapshot = join_paths(get_lvim_base_dir(), "snapshots", "default.json") +local plugins_dir = join_paths(get_runtime_dir(), "site", "pack", "lazy", "opt") function plugin_loader.init(opts) opts = opts or {} - local install_path = opts.install_path - or join_paths(vim.fn.stdpath "data", "site", "pack", "packer", "start", "packer.nvim") + local lazy_install_dir = opts.install_path + or join_paths(vim.fn.stdpath "data", "site", "pack", "lazy", "opt", "lazy.nvim") - local max_jobs = 100 - if vim.fn.has "mac" == 1 then - max_jobs = 50 - end - - local init_opts = { - package_root = opts.package_root or join_paths(vim.fn.stdpath "data", "site", "pack"), - compile_path = compile_path, - snapshot_path = snapshot_path, - max_jobs = max_jobs, - log = { level = "warn" }, - git = { - clone_timeout = 120, - }, - display = { - open_fn = function() - return require("packer.util").float { border = "rounded" } - end, - }, - } - - if in_headless then - init_opts.display = nil - init_opts.git.clone_timeout = 300 - end - - if not utils.is_directory(install_path) then + if not utils.is_directory(lazy_install_dir) then print "Initializing first time setup" - print "Installing packer" - print(vim.fn.system { "git", "clone", "--depth", "1", "https://github.com/wbthomason/packer.nvim", install_path }) - vim.cmd "packadd packer.nvim" - end + local core_plugins_dir = join_paths(get_lvim_base_dir(), "plugins") + if utils.is_directory(core_plugins_dir) then + vim.fn.mkdir(plugins_dir, "p") + vim.loop.fs_rmdir(plugins_dir) + require("lvim.utils").fs_copy(core_plugins_dir, plugins_dir) + else + vim.fn.system { + "git", + "clone", + "--filter=blob:none", + "--branch=stable", + "https://github.com/folke/lazy.nvim.git", + lazy_install_dir, + } - local status_ok, packer = pcall(require, "packer") - if status_ok then - packer.on_complete = vim.schedule_wrap(function() - require("lvim.utils.hooks").run_on_packer_complete() - end) - packer.init(init_opts) - end -end - --- packer expects a space separated list -local function pcall_packer_command(cmd, kwargs) - local status_ok, msg = pcall(function() - require("packer")[cmd](unpack(kwargs or {})) - end) - if not status_ok then - Log:warn(cmd .. " failed with: " .. vim.inspect(msg)) - Log:trace(vim.inspect(vim.fn.eval "v:errmsg")) - end -end - -function plugin_loader.cache_clear() - if not utils.is_file(compile_path) then - return - end - if vim.fn.delete(compile_path) == 0 then - Log:debug "deleted packer_compiled.lua" - end -end - -function plugin_loader.compile() - Log:debug "calling packer.compile()" - vim.api.nvim_create_autocmd("User", { - pattern = "PackerCompileDone", - once = true, - callback = function() - if utils.is_file(compile_path) then - Log:debug "finished compiling packer_compiled.lua" - end - end, - }) - pcall_packer_command "compile" -end - -function plugin_loader.recompile() - plugin_loader.cache_clear() - plugin_loader.compile() -end - -function plugin_loader.reload(configurations) - _G.packer_plugins = _G.packer_plugins or {} - for k, v in pairs(_G.packer_plugins) do - if k ~= "packer.nvim" then - _G.packer_plugins[v] = nil + local default_snapshot_path = join_paths(get_lvim_base_dir(), "snapshots", "default.json") + local snapshot = assert(vim.fn.json_decode(vim.fn.readfile(default_snapshot_path))) + vim.fn.system { + "git", + "-C", + lazy_install_dir, + "checkout", + snapshot["lazy.nvim"].commit, + } end end - plugin_loader.load(configurations) - plugin_loader.ensure_plugins() + vim.opt.runtimepath:append(lazy_install_dir) + vim.opt.runtimepath:append(join_paths(plugins_dir, "*")) + + local lazy_cache = require "lazy.core.cache" + lazy_cache.setup { + performance = { + cache = { + enabled = true, + path = join_paths(get_cache_dir(), "lazy", "cache"), + }, + }, + } + -- HACK: Don't allow lazy to call setup second time + lazy_cache.setup = function() end +end + +function plugin_loader.reset_cache() + os.remove(require("lazy.core.cache").config.path) +end + +function plugin_loader.reload(spec) + local Config = require "lazy.core.config" + local lazy = require "lazy" + + -- TODO: reset cache? and unload plugins? + + Config.spec = spec + + require("lazy.core.plugin").load(true) + require("lazy.core.plugin").update_state() + + local not_installed_plugins = vim.tbl_filter(function(plugin) + return not plugin._.installed + end, Config.plugins) + + require("lazy.manage").clear() + + if #not_installed_plugins > 0 then + lazy.install { wait = true } + end + + if #Config.to_clean > 0 then + -- TODO: set show to true when lazy shows something useful on clean + lazy.clean { wait = true, show = false } + end end function plugin_loader.load(configurations) Log:debug "loading plugins configuration" - local packer_available, packer = pcall(require, "packer") - if not packer_available then - Log:warn "skipping loading plugins until Packer is installed" + local lazy_available, lazy = pcall(require, "lazy") + if not lazy_available then + Log:warn "skipping loading plugins until lazy.nvim is installed" return end - local status_ok, _ = xpcall(function() - packer.reset() - packer.startup(function(use) - for _, plugins in ipairs(configurations) do - for _, plugin in ipairs(plugins) do - use(plugin) - end - end - end) + + -- remove plugins from rtp before loading lazy, so that all plugins won't be loaded on startup + vim.opt.runtimepath:remove(join_paths(plugins_dir, "*")) + + local status_ok = xpcall(function() + local opts = { + install = { + missing = true, + colorscheme = { lvim.colorscheme, "lunar", "habamax" }, + }, + ui = { + border = "rounded", + }, + root = plugins_dir, + git = { + timeout = 120, + }, + lockfile = join_paths(get_config_dir(), "lazy-lock.json"), + performance = { + rtp = { + reset = false, + }, + }, + readme = { + root = join_paths(get_runtime_dir(), "lazy", "readme"), + }, + } + + lazy.setup(configurations, opts) end, debug.traceback) if not status_ok then @@ -134,43 +133,26 @@ function plugin_loader.load(configurations) end function plugin_loader.get_core_plugins() - local list = {} + local names = {} local plugins = require "lvim.plugins" - for _, item in pairs(plugins) do - if not item.disable then - table.insert(list, item[1]:match "/(%S*)") + local get_name = require("lazy.core.plugin").Spec.get_name + for _, spec in pairs(plugins) do + if spec.enabled == true or spec.enabled == nil then + table.insert(names, get_name(spec[1])) end end - return list -end - -function plugin_loader.load_snapshot(snapshot_file) - snapshot_file = snapshot_file or default_snapshot - if not in_headless then - vim.notify("Syncing core plugins is in progress..", vim.log.levels.INFO, { title = "lvim" }) - end - Log:debug(string.format("Using snapshot file [%s]", snapshot_file)) - local core_plugins = plugin_loader.get_core_plugins() - require("packer").rollback(snapshot_file, unpack(core_plugins)) + return names end function plugin_loader.sync_core_plugins() - plugin_loader.cache_clear() local core_plugins = plugin_loader.get_core_plugins() Log:trace(string.format("Syncing core plugins: [%q]", table.concat(core_plugins, ", "))) - pcall_packer_command("sync", core_plugins) + require("lazy").sync { wait = true, plugins = core_plugins } end function plugin_loader.ensure_plugins() - vim.api.nvim_create_autocmd("User", { - pattern = "PackerComplete", - once = true, - callback = function() - plugin_loader.compile() - end, - }) - Log:debug "calling packer.install()" - pcall_packer_command "install" + Log:debug "calling lazy.install()" + require("lazy").install { wait = true } end return plugin_loader diff --git a/lua/lvim/plugins.lua b/lua/lvim/plugins.lua index 6a6c3db7..74de79e0 100644 --- a/lua/lvim/plugins.lua +++ b/lua/lvim/plugins.lua @@ -1,13 +1,14 @@ -- local require = require("lvim.utils.require").require local core_plugins = { - -- Packer can manage itself as an optional plugin - { "wbthomason/packer.nvim" }, - { "neovim/nvim-lspconfig" }, - { "tamago324/nlsp-settings.nvim" }, + { "folke/lazy.nvim", tag = "stable" }, { - "jose-elias-alvarez/null-ls.nvim", + "neovim/nvim-lspconfig", + lazy = true, + dependencies = { "mason-lspconfig.nvim", "nlsp-settings.nvim" }, }, - { "williamboman/mason-lspconfig.nvim" }, + { "williamboman/mason-lspconfig.nvim", lazy = true }, + { "tamago324/nlsp-settings.nvim", lazy = true }, + { "jose-elias-alvarez/null-ls.nvim", lazy = true }, { "williamboman/mason.nvim", config = function() @@ -31,14 +32,12 @@ local core_plugins = { config = function() require("lvim.core.telescope").setup() end, - disable = not lvim.builtin.telescope.active, - }, - { - "nvim-telescope/telescope-fzf-native.nvim", - requires = { "nvim-telescope/telescope.nvim" }, - run = "make", - disable = not lvim.builtin.telescope.active, + dependencies = { "telescope-fzf-native.nvim" }, + lazy = true, + cmd = "Telescope", + enabled = lvim.builtin.telescope.active, }, + { "nvim-telescope/telescope-fzf-native.nvim", build = "make", lazy = true, enabled = lvim.builtin.telescope.active }, -- Install nvim-cmp, and buffer source as a dependency { "hrsh7th/nvim-cmp", @@ -47,21 +46,25 @@ local core_plugins = { require("lvim.core.cmp").setup() end end, - requires = { - "L3MON4D3/LuaSnip", + event = { "InsertEnter", "CmdlineEnter" }, + dependencies = { + "cmp-nvim-lsp", + "cmp_luasnip", + "cmp-buffer", + "cmp-path", }, }, - { - "rafamadriz/friendly-snippets", - disable = not lvim.builtin.luasnip.sources.friendly_snippets, - }, + { "hrsh7th/cmp-nvim-lsp", lazy = true }, + { "saadparwaiz1/cmp_luasnip", lazy = true }, + { "hrsh7th/cmp-buffer", lazy = true }, + { "hrsh7th/cmp-path", lazy = true }, { "L3MON4D3/LuaSnip", config = function() local utils = require "lvim.utils" local paths = {} if lvim.builtin.luasnip.sources.friendly_snippets then - paths[#paths + 1] = utils.join_paths(get_runtime_dir(), "site", "pack", "packer", "start", "friendly-snippets") + paths[#paths + 1] = utils.join_paths(get_runtime_dir(), "site", "pack", "lazy", "opt", "friendly-snippets") end local user_snippets = utils.join_paths(get_config_dir(), "snippets") if utils.is_directory(user_snippets) then @@ -73,32 +76,25 @@ local core_plugins = { } require("luasnip.loaders.from_snipmate").lazy_load() end, + event = "InsertEnter", + dependencies = { + "friendly-snippets", + }, }, - { - "hrsh7th/cmp-nvim-lsp", - }, - { - "saadparwaiz1/cmp_luasnip", - }, - { - "hrsh7th/cmp-buffer", - }, - { - "hrsh7th/cmp-path", - }, + { "rafamadriz/friendly-snippets", lazy = true, cond = lvim.builtin.luasnip.sources.friendly_snippets }, { "folke/neodev.nvim", - module = "neodev", + lazy = true, }, -- Autopairs { "windwp/nvim-autopairs", - -- event = "InsertEnter", + event = "InsertEnter", config = function() require("lvim.core.autopairs").setup() end, - disable = not lvim.builtin.autopairs.active, + enabled = lvim.builtin.autopairs.active, }, -- Treesitter @@ -111,7 +107,7 @@ local core_plugins = { }, { "JoosepAlviste/nvim-ts-context-commentstring", - event = "BufReadPost", + event = "VeryLazy", }, -- NvimTree @@ -122,7 +118,7 @@ local core_plugins = { config = function() require("lvim.core.nvimtree").setup() end, - disable = not lvim.builtin.nvimtree.active, + enabled = lvim.builtin.nvimtree.active, }, -- Lir { @@ -130,17 +126,15 @@ local core_plugins = { config = function() require("lvim.core.lir").setup() end, - requires = { "kyazdani42/nvim-web-devicons" }, - disable = not lvim.builtin.lir.active, + enabled = lvim.builtin.lir.active, }, { "lewis6991/gitsigns.nvim", - config = function() require("lvim.core.gitsigns").setup() end, event = "BufRead", - disable = not lvim.builtin.gitsigns.active, + enabled = lvim.builtin.gitsigns.active, }, -- Whichkey @@ -149,8 +143,8 @@ local core_plugins = { config = function() require("lvim.core.which-key").setup() end, - event = "BufWinEnter", - disable = not lvim.builtin.which_key.active, + event = "VeryLazy", + enabled = lvim.builtin.which_key.active, }, -- Comments @@ -160,7 +154,7 @@ local core_plugins = { config = function() require("lvim.core.comment").setup() end, - disable = not lvim.builtin.comment.active, + enabled = lvim.builtin.comment.active, }, -- project.nvim @@ -169,13 +163,13 @@ local core_plugins = { config = function() require("lvim.core.project").setup() end, - disable = not lvim.builtin.project.active, + enabled = lvim.builtin.project.active, }, -- Icons { "kyazdani42/nvim-web-devicons", - disable = not lvim.use_icons, + enabled = lvim.use_icons, }, -- Status Line and Bufferline @@ -186,7 +180,7 @@ local core_plugins = { config = function() require("lvim.core.lualine").setup() end, - disable = not lvim.builtin.lualine.active, + enabled = lvim.builtin.lualine.active, }, -- breadcrumbs @@ -195,7 +189,7 @@ local core_plugins = { config = function() require("lvim.core.breadcrumbs").setup() end, - disable = not lvim.builtin.breadcrumbs.active, + enabled = lvim.builtin.breadcrumbs.active, }, { @@ -204,8 +198,7 @@ local core_plugins = { require("lvim.core.bufferline").setup() end, branch = "main", - event = "BufWinEnter", - disable = not lvim.builtin.bufferline.active, + enabled = lvim.builtin.bufferline.active, }, -- Debugging @@ -215,7 +208,7 @@ local core_plugins = { config = function() require("lvim.core.dap").setup() end, - disable = not lvim.builtin.dap.active, + enabled = lvim.builtin.dap.active, }, -- Debugger user interface @@ -224,7 +217,7 @@ local core_plugins = { config = function() require("lvim.core.dap").setup_ui() end, - disable = not lvim.builtin.dap.active, + enabled = lvim.builtin.dap.active, }, -- alpha @@ -233,23 +226,24 @@ local core_plugins = { config = function() require("lvim.core.alpha").setup() end, - disable = not lvim.builtin.alpha.active, + enabled = lvim.builtin.alpha.active, }, -- Terminal { "akinsho/toggleterm.nvim", - event = "BufWinEnter", + event = "VeryLazy", branch = "main", config = function() require("lvim.core.terminal").setup() end, - disable = not lvim.builtin.terminal.active, + enabled = lvim.builtin.terminal.active, }, -- SchemaStore { "b0o/schemastore.nvim", + lazy = true, }, { @@ -257,7 +251,8 @@ local core_plugins = { config = function() require("lvim.core.illuminate").setup() end, - disable = not lvim.builtin.illuminate.active, + event = "VeryLazy", + enabled = lvim.builtin.illuminate.active, }, { @@ -265,7 +260,7 @@ local core_plugins = { config = function() require("lvim.core.indentlines").setup() end, - disable = not lvim.builtin.indentlines.active, + enabled = lvim.builtin.indentlines.active, }, { @@ -279,7 +274,7 @@ local core_plugins = { end end) end, - disable = lvim.colorscheme ~= "onedarker", + enabled = lvim.colorscheme == "onedarker", }, { @@ -289,22 +284,29 @@ local core_plugins = { require("bigfile").config(lvim.builtin.bigfile.config) end) end, - disable = not lvim.builtin.bigfile.active, + enabled = lvim.builtin.bigfile.active, }, } local default_snapshot_path = join_paths(get_lvim_base_dir(), "snapshots", "default.json") local content = vim.fn.readfile(default_snapshot_path) -local default_sha1 = vim.fn.json_decode(content) +local default_sha1 = assert(vim.fn.json_decode(content)) + +-- taken form +local get_short_name = function(long_name) + local name = long_name:sub(-4) == ".git" and long_name:sub(1, -5) or long_name + local slash = name:reverse():find("/", 1, true) --[[@as number?]] + return slash and name:sub(#name - slash + 2) or long_name:gsub("%W+", "_") +end local get_default_sha1 = function(spec) - local short_name, _ = require("packer.util").get_plugin_short_name(spec) + local short_name = get_short_name(spec[1]) return default_sha1[short_name] and default_sha1[short_name].commit end if not vim.env.LVIM_DEV_MODE then + -- Manually lock the commit hashes of core plugins for _, spec in ipairs(core_plugins) do - -- Manually lock the commit hash since Packer's snapshots are unreliable in headless mode spec["commit"] = get_default_sha1(spec) end end diff --git a/lua/lvim/utils.lua b/lua/lvim/utils.lua index 71ede6e6..5e49906a 100644 --- a/lua/lvim/utils.lua +++ b/lua/lvim/utils.lua @@ -104,4 +104,29 @@ function M.write_file(path, txt, flag) end) end +---Copies a file or directory recursively +---@param source string +---@param destination string +function M.fs_copy(source, destination) + local source_stats = assert(vim.loop.fs_stat(source)) + + if source_stats.type == "file" then + assert(vim.loop.fs_copyfile(source, destination)) + return + elseif source_stats.type == "directory" then + local handle = assert(vim.loop.fs_scandir(source)) + + assert(vim.loop.fs_mkdir(destination, source_stats.mode)) + + while true do + local name = vim.loop.fs_scandir_next(handle) + if not name then + break + end + + M.fs_copy(M.join_paths(source, name), M.join_paths(destination, name)) + end + end +end + return M diff --git a/lua/lvim/utils/hooks.lua b/lua/lvim/utils/hooks.lua index 0194888d..54fea0c0 100644 --- a/lua/lvim/utils/hooks.lua +++ b/lua/lvim/utils/hooks.lua @@ -12,31 +12,22 @@ function M.run_pre_reload() Log:debug "Starting pre-reload hook" end -function M.run_on_packer_complete() - Log:debug "Packer operation complete" - vim.api.nvim_exec_autocmds("User", { pattern = "PackerComplete" }) - - -- -- FIXME(kylo252): nvim-tree.lua/lua/nvim-tree/view.lua:442: Invalid window id - -- vim.g.colors_name = lvim.colorscheme - -- pcall(vim.cmd.colorscheme, lvim.colorscheme) - - if M._reload_triggered then - Log:debug "Reloaded configuration" - M._reload_triggered = nil - end -end +-- TODO: convert to lazy.nvim +-- function M.run_on_packer_complete() +-- -- FIXME(kylo252): nvim-tree.lua/lua/nvim-tree/view.lua:442: Invalid window id +-- vim.g.colors_name = lvim.colorscheme +-- pcall(vim.cmd.colorscheme, lvim.colorscheme) +-- end function M.run_post_reload() Log:debug "Starting post-reload hook" - M._reload_triggered = true end ----Reset any startup cache files used by Packer and Impatient +---Reset any startup cache files used by lazy.nvim ---It also forces regenerating any template ftplugin files ---Tip: Useful for clearing any outdated settings function M.reset_cache() - vim.cmd [[LuaCacheClear]] - plugin_loader.recompile() + plugin_loader.reset_cache() local lvim_modules = {} for module, _ in pairs(package.loaded) do if module:match "lvim.core" or module:match "lvim.lsp" then @@ -57,9 +48,7 @@ function M.run_post_update() "Please upgrade your Neovim base installation. Newer version of Lunarvim requires v0.7+", vim.log.levels.WARN ) - vim.wait(1000, function() - return false - end) + vim.wait(1000) local ret = reload("lvim.utils.git").switch_lvim_branch(compat_tag) if ret then vim.notify("Reverted to the last known compatible version: " .. compat_tag, vim.log.levels.WARN) diff --git a/snapshots/default.json b/snapshots/default.json index 10ff2649..b9801e1c 100644 --- a/snapshots/default.json +++ b/snapshots/default.json @@ -35,6 +35,9 @@ "indent-blankline.nvim": { "commit": "c4c203c" }, + "lazy.nvim": { + "commit": "d211027" + }, "lir.nvim": { "commit": "ae190c3" }, @@ -92,9 +95,6 @@ "onedarker.nvim": { "commit": "b00dd21" }, - "packer.nvim": { - "commit": "dac4088" - }, "plenary.nvim": { "commit": "bb44479" }, diff --git a/tests/minimal_lsp.lua b/tests/minimal_lsp.lua index 01e814be..9515268f 100644 --- a/tests/minimal_lsp.lua +++ b/tests/minimal_lsp.lua @@ -13,25 +13,21 @@ local temp_dir = vim.loop.os_getenv "TEMP" or "/tmp" vim.cmd("set packpath=" .. join_paths(temp_dir, "nvim", "site")) local package_root = join_paths(temp_dir, "nvim", "site", "pack") -local install_path = join_paths(package_root, "packer", "start", "packer.nvim") -local compile_path = join_paths(install_path, "plugin", "packer_compiled.lua") +local plugins_dir = join_paths(package_root, "lazy", "opt") +local install_path = join_paths(package_root, "lazy.nvim") -- Choose whether to use the executable that's managed by mason local use_lsp_installer = true local function load_plugins() - require("packer").startup { - { - "wbthomason/packer.nvim", - "neovim/nvim-lspconfig", - "williamboman/mason-lspconfig.nvim", - "williamboman/mason.nvim", - }, - config = { - package_root = package_root, - compile_path = compile_path, - }, - } + vim.opt.rtp:prepend(install_path) + require("lazy").setup({ + "neovim/nvim-lspconfig", + "williamboman/mason-lspconfig.nvim", + "williamboman/mason.nvim", + }, { + root = plugins_dir, + }) end function _G.dump(...) @@ -98,12 +94,19 @@ _G.load_config = function() end if vim.fn.isdirectory(install_path) == 0 then - vim.fn.system { "git", "clone", "https://github.com/wbthomason/packer.nvim", install_path } + print "Installing lazy.nvim" + vim.fn.system { + "git", + "clone", + "--filter=blob:none", + "--single-branch", + "https://github.com/folke/lazy.nvim.git", + install_path, + } load_plugins() - require("packer").sync() - vim.cmd [[autocmd User PackerComplete ++once lua load_config()]] + vim.cmd [[autocmd User LazyDone ++once lua load_config()]] else load_plugins() - require("packer").sync() + require("lazy").sync() _G.load_config() end diff --git a/tests/specs/plugins_load_spec.lua b/tests/specs/plugins_load_spec.lua index 5cf1c2f5..37294c2e 100644 --- a/tests/specs/plugins_load_spec.lua +++ b/tests/specs/plugins_load_spec.lua @@ -6,16 +6,16 @@ a.describe("plugin-loader", function() pcall(function() lvim.log.level = "debug" - package.loaded["packer.log"] = nil package.loaded["lvim.core.log"] = nil end) a.it("should be able to load default packages without errors", function() + vim.go.loadplugins = true loader.load { plugins, lvim.plugins } -- TODO: maybe there's a way to avoid hard-coding the names of the modules? local startup_plugins = { - "packer", + "lazy", } for _, plugin in ipairs(startup_plugins) do @@ -24,8 +24,6 @@ a.describe("plugin-loader", function() end) a.it("should be able to load lsp packages without errors", function() - loader.load { plugins, lvim.plugins } - require("lvim.lsp").setup() local lsp_packages = { @@ -38,37 +36,4 @@ a.describe("plugin-loader", function() assert.truthy(package.loaded[plugin]) end end) - - pending("should be able to rollback plugins without errors", function() - local plugin = { name = "onedarker.nvim" } - plugin.path = vim.tbl_filter(function(package) - return package:match(plugin.name) - end, vim.api.nvim_list_runtime_paths())[1] - - local get_current_sha = function(repo) - local res = vim.fn.system(string.format("git -C %s log -1 --pretty=%%h", repo)):gsub("\n", "") - return res - end - plugin.test_sha = "316b1c9" - _G.locked_sha = get_current_sha(plugin.path) - loader.load { plugins, lvim.plugins } - - os.execute(string.format("git -C %s fetch --deepen 999 --quiet", plugin.path)) - os.execute(string.format("git -C %s checkout %s --quiet", plugin.path, plugin.test_sha)) - assert.equal(plugin.test_sha, get_current_sha(plugin.path)) - _G.completed = false - _G.verify_sha = function() - if _G.locked_sha ~= get_current_sha(plugin.path) then - error "unmatched results!" - else - _G.completed = true - end - end - vim.cmd [[autocmd User PackerComplete ++once lua _G.verify_sha()]] - loader.load_snapshot() - local ret = vim.wait(30 * 10 * 1000, function() - return _G.completed == true - end, 200) - assert.True(ret) - end) end) diff --git a/utils/ci/generate_new_lockfile.lua b/utils/ci/generate_new_lockfile.lua index 8eef5184..2677b202 100644 --- a/utils/ci/generate_new_lockfile.lua +++ b/utils/ci/generate_new_lockfile.lua @@ -71,6 +71,7 @@ local function write_lockfile(verbose) url = url, commit = commit, branch = plugin.branch or "HEAD", + tag = plugin.tag, }) end @@ -86,12 +87,20 @@ local function write_lockfile(verbose) return end local latest_sha = result:gsub("\tHEAD\n", ""):sub(1, 7) + if entry.tag then + local dereferenced_commit = result:match("\n(.*)\trefs/tags/" .. entry.tag .. "%^{}\n") + if dereferenced_commit then + latest_sha = dereferenced_commit:sub(1, 7) + end + end plugins_list[entry.name] = { commit = latest_sha, } end - local handle = call_proc("git", { args = { "ls-remote", entry.url, entry.branch } }, on_done) + local handle = call_proc("git", { + args = { "ls-remote", entry.url, entry.tag and entry.tag .. "*" or entry.branch }, + }, on_done) assert(handle) table.insert(active_jobs, handle) end diff --git a/utils/ci/verify_plugins.lua b/utils/ci/verify_plugins.lua index d009cbda..95d98a1e 100644 --- a/utils/ci/verify_plugins.lua +++ b/utils/ci/verify_plugins.lua @@ -24,28 +24,23 @@ local get_default_sha1 = function(spec) end local is_directory = require("lvim.utils").is_directory --- see packer.init() -local packdir = join_paths(get_runtime_dir(), "site", "pack", "packer") +local lazydir = join_paths(get_runtime_dir(), "site", "pack", "lazy") -local verify_packer = function() - if not is_directory(packdir) then - io.write "Packer not installed!" +local verify_lazy = function() + if not is_directory(lazydir) then + io.write "Lazy.nvim not installed!" os.exit(1) end - local status_ok, packer = pcall(require, "packer") - if status_ok and packer then + local status_ok, lazy = pcall(require, "lazy") + if status_ok and lazy then return end - io.write "Packer not installed!" + io.write "Lazy.nvim not installed!" os.exit(1) end -local packer_config = { opt_dir = join_paths(packdir, "opt"), start_dir = join_paths(packdir, "start") } -local is_optional = function(spec) - return spec.opt or spec.event or spec.cmd or spec.module -end local get_install_path = function(spec) - local prefix = is_optional(spec) and packer_config.opt_dir or packer_config.start_dir + local prefix = join_paths(lazydir, "opt") local path = join_paths(prefix, get_short_name(spec)) return is_directory(path) and path end @@ -79,7 +74,9 @@ local function call_proc(process, opts, cb) { args = opts.args, cwd = opts.cwd or uv.cwd(), stdio = stdio }, vim.schedule_wrap(function(code) if code ~= 0 then + ---@diagnostic disable-next-line: undefined-field stdout:read_stop() + ---@diagnostic disable-next-line: undefined-field stderr:read_stop() end @@ -106,7 +103,7 @@ end local function verify_core_plugins(verbose) for _, spec in pairs(core_plugins) do local path = get_install_path(spec) - if not spec.disable and path then + if spec.enabled or spec.enabled == nil and path then table.insert(collection, { name = get_short_name(spec), commit = get_default_sha1(spec), @@ -140,10 +137,11 @@ local function verify_core_plugins(verbose) end vim.wait(#active_jobs * 60 * 1000, function() + ---@diagnostic disable-next-line: redundant-return-value return completed == #active_jobs end) end -verify_packer() +verify_lazy() verify_core_plugins() vim.cmd "q" diff --git a/utils/installer/config.example.lua b/utils/installer/config.example.lua index b779717d..a1b2c9c9 100644 --- a/utils/installer/config.example.lua +++ b/utils/installer/config.example.lua @@ -33,7 +33,6 @@ lvim.keys.normal_mode[""] = ":w" -- -- Change theme settings -- lvim.colorscheme = "lunar" --- After changing plugin config exit and reopen LunarVim, Run :PackerSync lvim.builtin.alpha.active = true lvim.builtin.alpha.mode = "dashboard" lvim.builtin.terminal.active = true diff --git a/utils/installer/config_win.example.lua b/utils/installer/config_win.example.lua index eec5ff88..3467c86e 100644 --- a/utils/installer/config_win.example.lua +++ b/utils/installer/config_win.example.lua @@ -55,7 +55,6 @@ lvim.keys.normal_mode[""] = ":w" -- -- Change theme settings -- lvim.colorscheme = "lunar" --- After changing plugin config exit and reopen LunarVim, Run :PackerSync lvim.builtin.alpha.active = true lvim.builtin.alpha.mode = "dashboard" lvim.builtin.terminal.active = true diff --git a/utils/installer/install.ps1 b/utils/installer/install.ps1 index 442d8622..db1427e5 100644 --- a/utils/installer/install.ps1 +++ b/utils/installer/install.ps1 @@ -217,7 +217,7 @@ function setup_lvim() { $exampleConfig = "$env:LUNARVIM_BASE_DIR\utils\installer\config_win.example.lua" Copy-Item -Force "$exampleConfig" "$env:LUNARVIM_CONFIG_DIR\config.lua" - Write-Host "Make sure to run `:PackerSync` at first launch" -ForegroundColor Green + Write-Host "Make sure to run `:Lazy sync` at first launch" -ForegroundColor Green create_alias diff --git a/utils/installer/install.sh b/utils/installer/install.sh index d1e17878..5519e8a7 100755 --- a/utils/installer/install.sh +++ b/utils/installer/install.sh @@ -222,7 +222,7 @@ function check_neovim_min_version() { function verify_core_plugins() { msg "Verifying core plugins" if ! bash "$LUNARVIM_BASE_DIR/utils/ci/verify_plugins.sh"; then - echo "[ERROR]: Unable to verify plugins, make sure to manually run ':PackerSync' when starting lvim for the first time." + echo "[ERROR]: Unable to verify plugins, make sure to manually run ':Lazy sync' when starting lvim for the first time." exit 1 fi echo "Verification complete!" @@ -412,15 +412,10 @@ function setup_shim() { } function remove_old_cache_files() { - local packer_cache="$LUNARVIM_CONFIG_DIR/plugin/packer_compiled.lua" - if [ -e "$packer_cache" ]; then - msg "Removing old packer cache file" - rm -f "$packer_cache" - fi - - if [ -e "$LUNARVIM_CACHE_DIR/luacache" ] || [ -e "$LUNARVIM_CACHE_DIR/lvim_cache" ]; then - msg "Removing old startup cache file" - rm -f "$LUNARVIM_CACHE_DIR/{luacache,lvim_cache}" + local lazy_cache="$LUNARVIM_CACHE_DIR/lazy/cache" + if [ -e "$lazy_cache" ]; then + msg "Removing old lazy cache file" + rm -f "$lazy_cache" fi } @@ -435,13 +430,11 @@ function setup_lvim() { [ ! -f "$LUNARVIM_CONFIG_DIR/config.lua" ] \ && cp "$LUNARVIM_BASE_DIR/utils/installer/config.example.lua" "$LUNARVIM_CONFIG_DIR/config.lua" - echo "Preparing Packer setup" + echo "Preparing Lazy setup" - "$INSTALL_PREFIX/bin/lvim" --headless \ - -c 'autocmd User PackerComplete quitall' \ - -c 'PackerSync' + "$INSTALL_PREFIX/bin/lvim" --headless -c 'quitall' - echo "Packer setup complete" + echo "Lazy setup complete" verify_core_plugins }