From a6b74f30d5aab79a40d932f449c0aa5d4a0c6934 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Tue, 26 Mar 2024 19:52:16 +0100 Subject: [PATCH] feat(ui): backdrop for the lazy floating window. Can be disabled with `opts.ui.backdrop` --- README.md | 117 ++++++++++++++++++++------------------- lua/lazy/core/config.lua | 5 +- lua/lazy/view/float.lua | 43 +++++++++++++- 3 files changed, 106 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 10fabe9..48f64ba 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ You can add the following Lua code to your `init.lua` to bootstrap **lazy.nvim** ```lua local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" -if not vim.loop.fs_stat(lazypath) then +if not vim.uv.fs_stat(lazypath) then vim.fn.system({ "git", "clone", @@ -308,11 +308,12 @@ return { -- leave nil when passing the spec as the first argument to setup() spec = nil, ---@type LazySpec lockfile = vim.fn.stdpath("config") .. "/lazy-lock.json", -- lockfile generated after running update. - concurrency = jit.os:find("Windows") and (vim.loop.available_parallelism() * 2) or nil, ---@type number limit the maximum amount of concurrent tasks + ---@type number? limit the maximum amount of concurrent tasks + concurrency = jit.os:find("Windows") and (vim.uv.available_parallelism() * 2) or nil, git = { -- defaults for the `Lazy log` command - -- log = { "-10" }, -- show the last 10 commits - log = { "-8" }, -- show commits from the last 3 days + -- log = { "--since=3 days ago" }, -- show commits from the last 3 days + log = { "-8" }, -- show the last 8 commits timeout = 120, -- kill processes that take more than 2 minutes url_format = "https://github.com/%s.git", -- lazy.nvim requires git >=2.19.0. If you really want to use lazy with an older version, @@ -339,6 +340,8 @@ return { wrap = true, -- wrap the lines in the ui -- The border to use for the UI window. Accepts same border values as |nvim_open_win()|. border = "none", + -- The backdrop opacity. 0 is fully opaque, 100 is fully transparent. + backdrop = 60, title = nil, ---@type string only works when border is not "none" title_pos = "center", ---@type "center" | "left" | "right" -- Show pills on top of the Lazy window @@ -346,7 +349,7 @@ return { icons = { cmd = " ", config = "", - event = "", + event = " ", ft = " ", init = " ", import = " ", @@ -358,7 +361,7 @@ return { runtime = " ", require = "󰢱 ", source = " ", - start = "", + start = " ", task = "✔ ", list = { "●", @@ -513,24 +516,24 @@ Any operation can be started from the UI, with a sub command or an API function: -| Command | Lua | Description | -| ------------------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| `:Lazy build {plugins}` | `require("lazy").build(opts)` | Rebuild a plugin | -| `:Lazy check [plugins]` | `require("lazy").check(opts?)` | Check for updates and show the log (git fetch) | -| `:Lazy clean [plugins]` | `require("lazy").clean(opts?)` | Clean plugins that are no longer needed | -| `:Lazy clear` | `require("lazy").clear()` | Clear finished tasks | -| `:Lazy debug` | `require("lazy").debug()` | Show debug information | -| `:Lazy health` | `require("lazy").health()` | Run `:checkhealth lazy` | -| `:Lazy help` | `require("lazy").help()` | Toggle this help page | -| `:Lazy home` | `require("lazy").home()` | Go back to plugin list | -| `:Lazy install [plugins]` | `require("lazy").install(opts?)` | Install missing plugins | -| `:Lazy load {plugins}` | `require("lazy").load(opts)` | Load a plugin that has not been loaded yet. Similar to `:packadd`. Like `:Lazy load foo.nvim`. Use `:Lazy! load` to skip `cond` checks. | -| `:Lazy log [plugins]` | `require("lazy").log(opts?)` | Show recent updates | -| `:Lazy profile` | `require("lazy").profile()` | Show detailed profiling | -| `:Lazy reload {plugins}` | `require("lazy").reload(opts)` | Reload a plugin (experimental!!) | +| Command | Lua | Description | +| --- | --- | --- | --- | +| `:Lazy build {plugins}` | `require("lazy").build(opts)` | Rebuild a plugin | +| `:Lazy check [plugins]` | `require("lazy").check(opts?)` | Check for updates and show the log (git fetch) | +| `:Lazy clean [plugins]` | `require("lazy").clean(opts?)` | Clean plugins that are no longer needed | +| `:Lazy clear` | `require("lazy").clear()` | Clear finished tasks | +| `:Lazy debug` | `require("lazy").debug()` | Show debug information | +| `:Lazy health` | `require("lazy").health()` | Run `:checkhealth lazy` | +| `:Lazy help` | `require("lazy").help()` | Toggle this help page | +| `:Lazy home` | `require("lazy").home()` | Go back to plugin list | +| `:Lazy install [plugins]` | `require("lazy").install(opts?)` | Install missing plugins | +| `:Lazy load {plugins}` | `require("lazy").load(opts)` | Load a plugin that has not been loaded yet. Similar to `:packadd`. Like `:Lazy load foo.nvim`. Use `:Lazy! load` to skip `cond` checks. | +| `:Lazy log [plugins]` | `require("lazy").log(opts?)` | Show recent updates | +| `:Lazy profile` | `require("lazy").profile()` | Show detailed profiling | +| `:Lazy reload {plugins}` | `require("lazy").reload(opts)` | Reload a plugin (experimental!!) | | `:Lazy restore [plugins]` | `require("lazy").restore(opts?)` | Updates all plugins to the state in the lockfile. For a single plugin: restore it to the state in the lockfile or to a given commit under the cursor | -| `:Lazy sync [plugins]` | `require("lazy").sync(opts?)` | Run install, clean and update | -| `:Lazy update [plugins]` | `require("lazy").update(opts?)` | Update plugins. This will also update the lockfile | +| `:Lazy sync [plugins]` | `require("lazy").sync(opts?)` | Run install, clean and update | +| `:Lazy update [plugins]` | `require("lazy").update(opts?)` | Update plugins. This will also update the lockfile | @@ -781,40 +784,40 @@ To uninstall **lazy.nvim**, you need to remove the following files and directori -| Highlight Group | Default Group | Description | -| --------------------- | -------------------------- | --------------------------------------------------- | -| **LazyButton** | **_CursorLine_** | | -| **LazyButtonActive** | **_Visual_** | | -| **LazyComment** | **_Comment_** | | -| **LazyCommit** | **_@variable.builtin_** | commit ref | -| **LazyCommitIssue** | **_Number_** | | -| **LazyCommitScope** | **_Italic_** | conventional commit scope | -| **LazyCommitType** | **_Title_** | conventional commit type | -| **LazyDimmed** | **_Conceal_** | property | -| **LazyDir** | **_@markup.link_** | directory | -| **LazyH1** | **_IncSearch_** | home button | -| **LazyH2** | **_Bold_** | titles | -| **LazyLocal** | **_Constant_** | | -| **LazyNoCond** | **_DiagnosticWarn_** | unloaded icon for a plugin where `cond()` was false | -| **LazyNormal** | **_NormalFloat_** | | -| **LazyProgressDone** | **_Constant_** | progress bar done | -| **LazyProgressTodo** | **_LineNr_** | progress bar todo | -| **LazyProp** | **_Conceal_** | property | -| **LazyReasonCmd** | **_Operator_** | | -| **LazyReasonEvent** | **_Constant_** | | -| **LazyReasonFt** | **_Character_** | | -| **LazyReasonImport** | **_Identifier_** | | -| **LazyReasonKeys** | **_Statement_** | | -| **LazyReasonPlugin** | **_Special_** | | -| **LazyReasonRequire** | **_@variable.parameter_** | | -| **LazyReasonRuntime** | **_@macro_** | | -| **LazyReasonSource** | **_Character_** | | -| **LazyReasonStart** | **_@variable.member_** | | -| **LazySpecial** | **_@punctuation.special_** | | -| **LazyTaskError** | **_ErrorMsg_** | task errors | -| **LazyTaskOutput** | **_MsgArea_** | task output | -| **LazyUrl** | **_@markup.link_** | url | -| **LazyValue** | **_@string_** | value of a property | +| Highlight Group | Default Group | Description | +| --- | --- | --- | +| **LazyButton** | ***CursorLine*** | | +| **LazyButtonActive** | ***Visual*** | | +| **LazyComment** | ***Comment*** | | +| **LazyCommit** | ***@variable.builtin*** | commit ref | +| **LazyCommitIssue** | ***Number*** | | +| **LazyCommitScope** | ***Italic*** | conventional commit scope | +| **LazyCommitType** | ***Title*** | conventional commit type | +| **LazyDimmed** | ***Conceal*** | property | +| **LazyDir** | ***@markup.link*** | directory | +| **LazyH1** | ***IncSearch*** | home button | +| **LazyH2** | ***Bold*** | titles | +| **LazyLocal** | ***Constant*** | | +| **LazyNoCond** | ***DiagnosticWarn*** | unloaded icon for a plugin where `cond()` was false | +| **LazyNormal** | ***NormalFloat*** | | +| **LazyProgressDone** | ***Constant*** | progress bar done | +| **LazyProgressTodo** | ***LineNr*** | progress bar todo | +| **LazyProp** | ***Conceal*** | property | +| **LazyReasonCmd** | ***Operator*** | | +| **LazyReasonEvent** | ***Constant*** | | +| **LazyReasonFt** | ***Character*** | | +| **LazyReasonImport** | ***Identifier*** | | +| **LazyReasonKeys** | ***Statement*** | | +| **LazyReasonPlugin** | ***Special*** | | +| **LazyReasonRequire** | ***@variable.parameter*** | | +| **LazyReasonRuntime** | ***@macro*** | | +| **LazyReasonSource** | ***Character*** | | +| **LazyReasonStart** | ***@variable.member*** | | +| **LazySpecial** | ***@punctuation.special*** | | +| **LazyTaskError** | ***ErrorMsg*** | task errors | +| **LazyTaskOutput** | ***MsgArea*** | task output | +| **LazyUrl** | ***@markup.link*** | url | +| **LazyValue** | ***@string*** | value of a property | diff --git a/lua/lazy/core/config.lua b/lua/lazy/core/config.lua index dc05600..4195336 100644 --- a/lua/lazy/core/config.lua +++ b/lua/lazy/core/config.lua @@ -17,7 +17,8 @@ M.defaults = { -- leave nil when passing the spec as the first argument to setup() spec = nil, ---@type LazySpec lockfile = vim.fn.stdpath("config") .. "/lazy-lock.json", -- lockfile generated after running update. - concurrency = jit.os:find("Windows") and (vim.uv.available_parallelism() * 2) or nil, ---@type number limit the maximum amount of concurrent tasks + ---@type number? limit the maximum amount of concurrent tasks + concurrency = jit.os:find("Windows") and (vim.uv.available_parallelism() * 2) or nil, git = { -- defaults for the `Lazy log` command -- log = { "--since=3 days ago" }, -- show commits from the last 3 days @@ -48,6 +49,8 @@ M.defaults = { wrap = true, -- wrap the lines in the ui -- The border to use for the UI window. Accepts same border values as |nvim_open_win()|. border = "none", + -- The backdrop opacity. 0 is fully opaque, 100 is fully transparent. + backdrop = 60, title = nil, ---@type string only works when border is not "none" title_pos = "center", ---@type "center" | "left" | "right" -- Show pills on top of the Lazy window diff --git a/lua/lazy/view/float.lua b/lua/lazy/view/float.lua index 0a21b38..3e8938f 100644 --- a/lua/lazy/view/float.lua +++ b/lua/lazy/view/float.lua @@ -15,12 +15,15 @@ local ViewConfig = require("lazy.view.config") ---@field persistent? boolean ---@field ft? string ---@field noautocmd? boolean +---@field backdrop? float ---@class LazyFloat ---@field buf number ---@field win number ---@field opts LazyFloatOptions ---@field win_opts LazyWinOpts +---@field backdrop_buf number +---@field backdrop_win number ---@overload fun(opts?:LazyFloatOptions):LazyFloat local M = {} @@ -43,6 +46,7 @@ function M:init(opts) size = Config.options.ui.size, style = "minimal", border = Config.options.ui.border or "none", + backdrop = Config.options.ui.backdrop or 60, zindex = 50, }, opts or {}) @@ -62,7 +66,7 @@ function M:init(opts) } self:mount() self:on_key(ViewConfig.keys.close, self.close) - self:on({ "BufDelete", "BufHidden" }, self.close, { once = true }) + self:on({ "BufDelete", "BufHidden" }, self.close, { once = false }) return self end @@ -114,6 +118,24 @@ function M:mount() self.buf = vim.api.nvim_create_buf(false, true) end + if self.opts.backdrop and self.opts.backdrop < 100 then + self.backdrop_buf = vim.api.nvim_create_buf(false, true) + self.backdrop_win = vim.api.nvim_open_win(self.backdrop_buf, false, { + relative = "editor", + width = vim.o.columns, + height = vim.o.lines, + row = 0, + col = 0, + style = "minimal", + focusable = false, + zindex = self.opts.zindex - 1, + }) + vim.api.nvim_set_hl(0, "LazyBackdrop", { bg = "#000000", default = true }) + Util.wo(self.backdrop_win, "winhighlight", "Normal:LazyBackdrop") + Util.wo(self.backdrop_win, "winblend", self.opts.backdrop) + vim.bo[self.backdrop_buf].buftype = "nofile" + end + self:layout() self.win = vim.api.nvim_open_win(self.buf, true, self.win_opts) self:focus() @@ -149,6 +171,14 @@ function M:mount() end config.style = self.opts.style ~= "" and self.opts.style or nil vim.api.nvim_win_set_config(self.win, config) + + if self.backdrop_win and vim.api.nvim_win_is_valid(self.backdrop_win) then + vim.api.nvim_win_set_config(self.backdrop_win, { + width = vim.o.columns, + height = vim.o.lines, + }) + end + opts() vim.api.nvim_exec_autocmds("User", { pattern = "LazyFloatResized", modeline = false }) end, @@ -204,7 +234,18 @@ function M:close(opts) if wipe then self.buf = nil end + local backdrop_buf = self.backdrop_buf + local backdrop_win = self.backdrop_win + self.backdrop_buf = nil + self.backdrop_win = nil + vim.schedule(function() + if backdrop_win and vim.api.nvim_win_is_valid(backdrop_win) then + vim.api.nvim_win_close(backdrop_win, true) + end + if backdrop_buf and vim.api.nvim_buf_is_valid(backdrop_buf) then + vim.api.nvim_buf_delete(backdrop_buf, { force = true }) + end if win and vim.api.nvim_win_is_valid(win) then vim.api.nvim_win_close(win, true) end