mirror of
https://github.com/LazyVim/LazyVim.git
synced 2026-07-25 14:01:06 +00:00
feat(format) adds mode for autoformat to apply either to the file or only the modified lines
This commit is contained in:
parent
cb223553ff
commit
2ea8bd564f
6 changed files with 123 additions and 11 deletions
|
|
@ -139,6 +139,8 @@ map("n", "[w", diagnostic_goto(false, "WARN"), { desc = "Prev Warning" })
|
||||||
-- toggle options
|
-- toggle options
|
||||||
LazyVim.format.snacks_toggle():map("<leader>uf")
|
LazyVim.format.snacks_toggle():map("<leader>uf")
|
||||||
LazyVim.format.snacks_toggle(true):map("<leader>uF")
|
LazyVim.format.snacks_toggle(true):map("<leader>uF")
|
||||||
|
LazyVim.format.snacks_mode_toggle():map("<leader>um")
|
||||||
|
LazyVim.format.snacks_mode_toggle(true):map("<leader>uM")
|
||||||
Snacks.toggle.option("spell", { name = "Spelling" }):map("<leader>us")
|
Snacks.toggle.option("spell", { name = "Spelling" }):map("<leader>us")
|
||||||
Snacks.toggle.option("wrap", { name = "Wrap" }):map("<leader>uw")
|
Snacks.toggle.option("wrap", { name = "Wrap" }):map("<leader>uw")
|
||||||
Snacks.toggle.option("relativenumber", { name = "Relative Number" }):map("<leader>uL")
|
Snacks.toggle.option("relativenumber", { name = "Relative Number" }):map("<leader>uL")
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,13 @@ vim.g.maplocalleader = "\\"
|
||||||
|
|
||||||
-- LazyVim auto format
|
-- LazyVim auto format
|
||||||
vim.g.autoformat = true
|
vim.g.autoformat = true
|
||||||
|
-- LazyVim auto format mode (files | changes)
|
||||||
|
-- if set to changes only format actual changes based on git hunks
|
||||||
|
-- otherwise format all the file
|
||||||
|
vim.g.formatmode = "file"
|
||||||
|
--- LazyVim auto format changes only mode will be ignored
|
||||||
|
--- for these filetypes and fallback to file
|
||||||
|
vim.g.format_range_exclude_ft = { "lua" }
|
||||||
|
|
||||||
-- Snacks animations
|
-- Snacks animations
|
||||||
-- Set to `false` to globally disable all snacks animations
|
-- Set to `false` to globally disable all snacks animations
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,7 @@ return {
|
||||||
topdelete = { text = "" },
|
topdelete = { text = "" },
|
||||||
changedelete = { text = "▎" },
|
changedelete = { text = "▎" },
|
||||||
},
|
},
|
||||||
|
attach_to_untracked = true,
|
||||||
on_attach = function(buffer)
|
on_attach = function(buffer)
|
||||||
local gs = package.loaded.gitsigns
|
local gs = package.loaded.gitsigns
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@ return {
|
||||||
name = "conform.nvim",
|
name = "conform.nvim",
|
||||||
priority = 100,
|
priority = 100,
|
||||||
primary = true,
|
primary = true,
|
||||||
format = function(buf)
|
format = function(buf, range)
|
||||||
require("conform").format({ bufnr = buf })
|
require("conform").format({ bufnr = buf, range = range })
|
||||||
end,
|
end,
|
||||||
sources = function(buf)
|
sources = function(buf)
|
||||||
local ret = require("conform").list_formatters(buf)
|
local ret = require("conform").list_formatters(buf)
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,17 @@ local M = setmetatable({}, {
|
||||||
---@class LazyFormatter
|
---@class LazyFormatter
|
||||||
---@field name string
|
---@field name string
|
||||||
---@field primary? boolean
|
---@field primary? boolean
|
||||||
---@field format fun(bufnr:number)
|
---@field format fun(bufnr:number, range?:{start:integer[],end:integer[]})
|
||||||
---@field sources fun(bufnr:number):string[]
|
---@field sources fun(bufnr:number):string[]
|
||||||
---@field priority number
|
---@field priority number
|
||||||
|
|
||||||
M.formatters = {} ---@type LazyFormatter[]
|
M.formatters = {} ---@type LazyFormatter[]
|
||||||
|
|
||||||
|
--- Exclude lua from range formatting as stylua does not handle it well
|
||||||
|
--- It will fallback to file formatting
|
||||||
|
---@type string[]
|
||||||
|
M.format_range_exclude_ft = { "lua" }
|
||||||
|
|
||||||
---@param formatter LazyFormatter
|
---@param formatter LazyFormatter
|
||||||
function M.register(formatter)
|
function M.register(formatter)
|
||||||
M.formatters[#M.formatters + 1] = formatter
|
M.formatters[#M.formatters + 1] = formatter
|
||||||
|
|
@ -52,13 +57,19 @@ function M.info(buf)
|
||||||
buf = buf or vim.api.nvim_get_current_buf()
|
buf = buf or vim.api.nvim_get_current_buf()
|
||||||
local gaf = vim.g.autoformat == nil or vim.g.autoformat
|
local gaf = vim.g.autoformat == nil or vim.g.autoformat
|
||||||
local baf = vim.b[buf].autoformat
|
local baf = vim.b[buf].autoformat
|
||||||
|
local gmode = (vim.g.formatmode == nil and "file") or vim.g.formatmode
|
||||||
|
local bmode = vim.b[buf].formatmode
|
||||||
|
if vim.tbl_contains(vim.g.format_range_exclude_ft or M.format_range_exclude_ft, vim.bo[buf].filetype) then
|
||||||
|
bmode = "forced file"
|
||||||
|
end
|
||||||
local enabled = M.enabled(buf)
|
local enabled = M.enabled(buf)
|
||||||
local lines = {
|
local lines = {
|
||||||
"# Status",
|
"\n# Status",
|
||||||
("- [%s] global **%s**"):format(gaf and "x" or " ", gaf and "enabled" or "disabled"),
|
("- [%s] global **%s** (`%s`)"):format(gaf and "x" or " ", gaf and "enabled" or "disabled", gmode),
|
||||||
("- [%s] buffer **%s**"):format(
|
("- [%s] buffer **%s** (`%s`)"):format(
|
||||||
enabled and "x" or " ",
|
enabled and "x" or " ",
|
||||||
baf == nil and "inherit" or baf and "enabled" or "disabled"
|
baf == nil and "inherit" or baf and "enabled" or "disabled",
|
||||||
|
bmode == nil and "inherit" or bmode
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
local have = false
|
local have = false
|
||||||
|
|
@ -115,20 +126,26 @@ function M.enable(enable, buf)
|
||||||
M.info()
|
M.info()
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param opts? {force?:boolean, buf?:number}
|
---@param opts? {force?:boolean, buf?:number, changes?:boolean}
|
||||||
function M.format(opts)
|
function M.format(opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
local buf = opts.buf or vim.api.nvim_get_current_buf()
|
local buf = opts.buf or vim.api.nvim_get_current_buf()
|
||||||
if not ((opts and opts.force) or M.enabled(buf)) then
|
if not ((opts and opts.force) or M.enabled(buf)) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
local range_exclude_ft = vim.g.format_range_exclude_ft or M.format_range_exclude_ft
|
||||||
|
|
||||||
|
local format = M._format_file
|
||||||
|
local mode = (opts.changes and "changes") or M.mode(buf)
|
||||||
|
if mode == "changes" and not vim.tbl_contains(range_exclude_ft, vim.bo[buf].filetype) then
|
||||||
|
format = M._format_changes
|
||||||
|
end
|
||||||
local done = false
|
local done = false
|
||||||
for _, formatter in ipairs(M.resolve(buf)) do
|
for _, formatter in ipairs(M.resolve(buf)) do
|
||||||
if formatter.active then
|
if formatter.active then
|
||||||
done = true
|
done = true
|
||||||
LazyVim.try(function()
|
LazyVim.try(function()
|
||||||
return formatter.format(buf)
|
return format(formatter, buf)
|
||||||
end, { msg = "Formatter `" .. formatter.name .. "` failed" })
|
end, { msg = "Formatter `" .. formatter.name .. "` failed" })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -138,6 +155,46 @@ function M.format(opts)
|
||||||
end
|
end
|
||||||
end
|
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
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param formatter LazyFormatter
|
||||||
|
---@param buf number
|
||||||
|
function M._format_file(formatter, buf)
|
||||||
|
return formatter.format(buf)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param mode "changes" | "file"
|
||||||
|
---@param buf? boolean
|
||||||
|
function M.setmode(mode, buf)
|
||||||
|
if buf then
|
||||||
|
vim.b.formatmode = mode
|
||||||
|
else
|
||||||
|
vim.g.formatmode = mode
|
||||||
|
vim.b.formatmode = nil
|
||||||
|
end
|
||||||
|
M.info()
|
||||||
|
end
|
||||||
|
|
||||||
function M.health()
|
function M.health()
|
||||||
local Config = require("lazy.core.config")
|
local Config = require("lazy.core.config")
|
||||||
local has_plugin = Config.spec.plugins["none-ls.nvim"]
|
local has_plugin = Config.spec.plugins["none-ls.nvim"]
|
||||||
|
|
@ -155,6 +212,29 @@ function M.health()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param buf? boolean
|
||||||
|
function M.togglemode(buf)
|
||||||
|
local mode = M.mode()
|
||||||
|
if mode == "file" then
|
||||||
|
mode = "changes"
|
||||||
|
else
|
||||||
|
mode = "file"
|
||||||
|
end
|
||||||
|
M.setmode(mode, buf)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param buf? number
|
||||||
|
---@return "changes" | "file"
|
||||||
|
function M.mode(buf)
|
||||||
|
buf = buf or vim.api.nvim_get_current_buf()
|
||||||
|
local gmode = (vim.g.formatmode == nil and "file") or vim.g.formatmode
|
||||||
|
local bmode = vim.b[buf].formatmode
|
||||||
|
if bmode == nil then
|
||||||
|
return gmode
|
||||||
|
end
|
||||||
|
return bmode
|
||||||
|
end
|
||||||
|
|
||||||
function M.setup()
|
function M.setup()
|
||||||
M.health()
|
M.health()
|
||||||
|
|
||||||
|
|
@ -177,6 +257,27 @@ function M.setup()
|
||||||
end, { desc = "Show info about the formatters for the current buffer" })
|
end, { desc = "Show info about the formatters for the current buffer" })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param buf? boolean
|
||||||
|
function M.snacks_mode_toggle(buf)
|
||||||
|
return Snacks.toggle({
|
||||||
|
name = "Format Changes only (" .. (buf and "Buffer" or "Global") .. ")",
|
||||||
|
get = function()
|
||||||
|
if not buf then
|
||||||
|
local mode = vim.g.formatmode == nil and "file" or vim.g.formatmode
|
||||||
|
return mode == "changes"
|
||||||
|
end
|
||||||
|
return LazyVim.format.mode() == "changes"
|
||||||
|
end,
|
||||||
|
set = function(state)
|
||||||
|
if state then
|
||||||
|
LazyVim.format.setmode("changes", buf)
|
||||||
|
else
|
||||||
|
LazyVim.format.setmode("file", buf)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
---@param buf? boolean
|
---@param buf? boolean
|
||||||
function M.snacks_toggle(buf)
|
function M.snacks_toggle(buf)
|
||||||
return Snacks.toggle({
|
return Snacks.toggle({
|
||||||
|
|
|
||||||
|
|
@ -162,8 +162,9 @@ function M.formatter(opts)
|
||||||
name = "LSP",
|
name = "LSP",
|
||||||
primary = true,
|
primary = true,
|
||||||
priority = 1,
|
priority = 1,
|
||||||
format = function(buf)
|
format = function(buf, range)
|
||||||
M.format(LazyVim.merge({}, filter, { bufnr = buf }))
|
local fopts = LazyVim.merge({}, filter, { bufnr = buf }, { range = range })
|
||||||
|
M.format(fopts)
|
||||||
end,
|
end,
|
||||||
sources = function(buf)
|
sources = function(buf)
|
||||||
local clients = M.get_clients(LazyVim.merge({}, filter, { bufnr = buf }))
|
local clients = M.get_clients(LazyVim.merge({}, filter, { bufnr = buf }))
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue