From 8506618955e9877c7209f639f0df682f2faf619f Mon Sep 17 00:00:00 2001 From: Antoine U Date: Tue, 7 Jan 2025 17:01:14 +0100 Subject: [PATCH] feat(format): removes hard dependency on gitsigns for format changes feature and add support for mini-diff --- lua/lazyvim/config/options.lua | 6 ++ lua/lazyvim/plugins/editor.lua | 24 ++++++++ .../plugins/extras/editor/mini-diff.lua | 25 +++++++++ lua/lazyvim/util/changes.lua | 56 +++++++++++++++++++ lua/lazyvim/util/format.lua | 20 ++----- lua/lazyvim/util/init.lua | 1 + 6 files changed, 116 insertions(+), 16 deletions(-) create mode 100644 lua/lazyvim/util/changes.lua diff --git a/lua/lazyvim/config/options.lua b/lua/lazyvim/config/options.lua index 5ae63ae2..d710ec74 100644 --- a/lua/lazyvim/config/options.lua +++ b/lua/lazyvim/config/options.lua @@ -14,6 +14,12 @@ vim.g.formatmode = "file" --- for these filetypes and fallback to file vim.g.format_range_exclude_ft = { "lua" } +-- LazyVim changes provider to use. +-- Can be one of: gitsigns, mini-diff +-- Leave it to "auto" to automatically use the provider +-- enabled with `:LazyExtras` +vim.g.lazyvim_changes_provider = "auto" + -- Snacks animations -- Set to `false` to globally disable all snacks animations vim.g.snacks_animate = true diff --git a/lua/lazyvim/plugins/editor.lua b/lua/lazyvim/plugins/editor.lua index 5ffe0d8b..efee8d14 100644 --- a/lua/lazyvim/plugins/editor.lua +++ b/lua/lazyvim/plugins/editor.lua @@ -1,3 +1,24 @@ +---@type LazyChangeProvider +local gitsigns_provider = { + name = "gitsigns", + changes = function(buf) + buf = buf or vim.api.get_current_buf(buf) + local hunks = require("gitsigns").get_hunks(buf) + if hunks == nil then + return nil + end + hunks = vim.tbl_filter(function(h) + return h and h.type ~= "delete" + end, hunks) + return vim.tbl_map(function(h) + local start = h.added.start + local last = start + h.added.count + local last_hunk_line = vim.api.nvim_buf_get_lines(0, last - 2, last - 1, true)[1] + return { start = { start, 0 }, ["end"] = { last - 1, last_hunk_line:len() } } + end, hunks) + end, +} + return { -- search/replace in multiple files @@ -123,6 +144,9 @@ return { { "lewis6991/gitsigns.nvim", event = "LazyFile", + init = function() + LazyVim.changes.register(gitsigns_provider) + end, opts = { signs = { add = { text = "▎" }, diff --git a/lua/lazyvim/plugins/extras/editor/mini-diff.lua b/lua/lazyvim/plugins/extras/editor/mini-diff.lua index fe25c11e..1448b486 100644 --- a/lua/lazyvim/plugins/extras/editor/mini-diff.lua +++ b/lua/lazyvim/plugins/extras/editor/mini-diff.lua @@ -1,3 +1,25 @@ +---@type LazyChangeProvider +local mini_diff_provider = { + name = "mini-diff", + changes = function(buf) + buf = buf or vim.api.get_current_buf(buf) + local data = MiniDiff.get_buf_data(buf) + if not data or not data.hunks then + return {} + end + local hunks = data.hunks + hunks = vim.tbl_filter(function(h) + return h and h.type ~= "delete" + end, hunks) + return vim.tbl_map(function(h) + local start = h.buf_start + local last = start + h.buf_count + local last_hunk_line = vim.api.nvim_buf_get_lines(0, last - 2, last - 1, true)[1] + return { start = { start, 0 }, ["end"] = { last - 1, last_hunk_line:len() } } + end, hunks) + end, +} + return { -- disable gitsigns.nvim { @@ -9,6 +31,9 @@ return { { "echasnovski/mini.diff", event = "VeryLazy", + init = function() + LazyVim.changes.register(mini_diff_provider) + end, keys = { { "go", diff --git a/lua/lazyvim/util/changes.lua b/lua/lazyvim/util/changes.lua new file mode 100644 index 00000000..dd827a50 --- /dev/null +++ b/lua/lazyvim/util/changes.lua @@ -0,0 +1,56 @@ +---@class lazyvim.util.changes +---@overload fun(buf:number):LazyChange[] +local M = setmetatable({}, { + __call = function(m, ...) + if m.provider and m.provider.changes then + return m.provider.changes(...) + end + LazyVim.warn("`LazyVim.changes`: provider is not set") + return {} + end, +}) + +---@class LazyChange +---@field start number +---@field end number + +---@class LazyChangeProvider +---@field name string +---@field changes fun(buf?:number):LazyChange[]? + +---@type LazyChangeProvider? +M.provider = nil + +---@param provider LazyChangeProvider +function M.register(provider) + -- this only happens when using :LazyExtras + -- so allow to get the full spec + if vim.v.vim_did_enter == 1 then + return true + end + if M.provider and M.provider.name ~= M.want() then + M.provider = nil + end + if M.provider and M.provider.name ~= provider.name then + LazyVim.warn( + "`LazyVim.changes`: provider already set to `" + .. M.provider.name + .. "`,\nignoring new provider `" + .. provider.name + .. "`" + ) + return false + end + M.provider = provider + return true +end + +---@return "gitsigns" | "mini-diff" +function M.want() + if not vim.g.lazyvim_changes_provider or vim.g.lazyvim_changes_provider == "auto" then + return LazyVim.has_extra("editor.mini-diff") and "mini-diff" or "gitsigns" + end + return vim.g.lazyvim_changes_provider +end + +return M diff --git a/lua/lazyvim/util/format.lua b/lua/lazyvim/util/format.lua index 4209de53..ed19adc7 100644 --- a/lua/lazyvim/util/format.lua +++ b/lua/lazyvim/util/format.lua @@ -158,22 +158,10 @@ end ---@param formatter LazyFormatter ---@param buf number function M._format_changes(formatter, buf) - if not LazyVim.has("gitsigns.nvim") then - return - end - local hunks = require("gitsigns").get_hunks(buf) - if hunks == nil then - return - end - for i = #hunks, 1, -1 do - local hunk = hunks[i] - if hunk ~= nil and hunk.type ~= "delete" then - local start = hunk.added.start - local last = start + hunk.added.count - local last_hunk_line = vim.api.nvim_buf_get_lines(0, last - 2, last - 1, true)[1] - local range = { start = { start, 0 }, ["end"] = { last - 1, last_hunk_line:len() } } - formatter.format(buf, range) - end + local changes = LazyVim.changes(buf) + for i = #changes, 1, -1 do + local change = changes[i] + formatter.format(buf, change) end end diff --git a/lua/lazyvim/util/init.lua b/lua/lazyvim/util/init.lua index 4b49f539..74bbb3f2 100644 --- a/lua/lazyvim/util/init.lua +++ b/lua/lazyvim/util/init.lua @@ -12,6 +12,7 @@ local LazyUtil = require("lazy.core.util") ---@field inject lazyvim.util.inject ---@field news lazyvim.util.news ---@field json lazyvim.util.json +---@field changes lazyvim.util.changes ---@field lualine lazyvim.util.lualine ---@field mini lazyvim.util.mini ---@field pick lazyvim.util.pick